home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / perl / sprite / RCS / doio.c,v < prev    next >
Encoding:
Text File  |  1991-11-14  |  61.4 KB  |  3,020 lines

  1. head     1.3;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.3
  10. date     91.11.14.12.52.09;  author jhh;  state Exp;
  11. branches ;
  12. next     1.2;
  13.  
  14. 1.2
  15. date     91.08.12.16.41.16;  author jhh;  state Exp;
  16. branches ;
  17. next     1.1;
  18.  
  19. 1.1
  20. date     91.07.19.11.38.39;  author jhh;  state Exp;
  21. branches ;
  22. next     ;
  23.  
  24.  
  25. desc
  26. @@
  27.  
  28.  
  29. 1.3
  30. log
  31. @patchlevel 19
  32. @
  33. text
  34. @/* $RCSfile: doio.c,v $$Revision: 1.2 $$Date: 91/08/12 16:41:16 $
  35.  *
  36.  *    Copyright (c) 1991, Larry Wall
  37.  *
  38.  *    You may distribute under the terms of either the GNU General Public
  39.  *    License or the Artistic License, as specified in the README file.
  40.  *
  41.  * $Log:    doio.c,v $
  42.  * Revision 4.0.1.4  91/11/05  16:51:43  lwall
  43.  * patch11: prepared for ctype implementations that don't define isascii()
  44.  * patch11: perl mistook some streams for sockets because they return mode 0 too
  45.  * patch11: reopening STDIN, STDOUT and STDERR failed on some machines
  46.  * patch11: certain perl errors should set EBADF so that $! looks better
  47.  * patch11: truncate on a closed filehandle could dump
  48.  * patch11: stats of _ forgot whether prior stat was actually lstat
  49.  * patch11: -T returned true on NFS directory
  50.  *
  51.  * Revision 1.2  91/08/12  16:41:16  jhh
  52.  * Sprite version of stat() returns a few extra fields
  53.  * 
  54.  * Revision 4.0.1.3  91/06/10  01:21:19  lwall
  55.  * patch10: read didn't work from character special files open for writing
  56.  * patch10: close-on-exec wrongly set on system file descriptors
  57.  * 
  58.  * Revision 4.0.1.2  91/06/07  10:53:39  lwall
  59.  * patch4: new copyright notice
  60.  * patch4: system fd's are now treated specially
  61.  * patch4: added $^F variable to specify maximum system fd, default 2
  62.  * patch4: character special files now opened with bidirectional stdio buffers
  63.  * patch4: taintchecks could improperly modify parent in vfork()
  64.  * patch4: many, many itty-bitty portability fixes
  65.  * 
  66.  * Revision 4.0.1.1  91/04/11  17:41:06  lwall
  67.  * patch1: hopefully straightened out some of the Xenix mess
  68.  * 
  69.  * Revision 4.0  91/03/20  01:07:06  lwall
  70.  * 4.0 baseline.
  71.  * 
  72.  */
  73.  
  74. #include "EXTERN.h"
  75. #include "perl.h"
  76.  
  77. #ifdef HAS_SOCKET
  78. #include <sys/socket.h>
  79. #include <netdb.h>
  80. #endif
  81.  
  82. #ifdef HAS_SELECT
  83. #ifdef I_SYS_SELECT
  84. #ifndef I_SYS_TIME
  85. #include <sys/select.h>
  86. #endif
  87. #endif
  88. #endif
  89.  
  90. #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
  91. #include <sys/ipc.h>
  92. #ifdef HAS_MSG
  93. #include <sys/msg.h>
  94. #endif
  95. #ifdef HAS_SEM
  96. #include <sys/sem.h>
  97. #endif
  98. #ifdef HAS_SHM
  99. #include <sys/shm.h>
  100. #endif
  101. #endif
  102.  
  103. #ifdef I_PWD
  104. #include <pwd.h>
  105. #endif
  106. #ifdef I_GRP
  107. #include <grp.h>
  108. #endif
  109. #ifdef I_UTIME
  110. #include <utime.h>
  111. #endif
  112. #ifdef I_FCNTL
  113. #include <fcntl.h>
  114. #endif
  115. #ifdef I_SYS_FILE
  116. #include <sys/file.h>
  117. #endif
  118.  
  119. int laststatval = -1;
  120. int laststype = O_STAT;
  121.  
  122. bool
  123. do_open(stab,name,len)
  124. STAB *stab;
  125. register char *name;
  126. int len;
  127. {
  128.     FILE *fp;
  129.     register STIO *stio = stab_io(stab);
  130.     char *myname = savestr(name);
  131.     int result;
  132.     int fd;
  133.     int writing = 0;
  134.     char mode[3];        /* stdio file mode ("r\0" or "r+\0") */
  135.     FILE *saveifp = Nullfp;
  136.     FILE *saveofp = Nullfp;
  137.     char savetype = ' ';
  138.  
  139.     name = myname;
  140.     forkprocess = 1;        /* assume true if no fork */
  141.     while (len && isSPACE(name[len-1]))
  142.     name[--len] = '\0';
  143.     if (!stio)
  144.     stio = stab_io(stab) = stio_new();
  145.     else if (stio->ifp) {
  146.     fd = fileno(stio->ifp);
  147.     if (stio->type == '-')
  148.         result = 0;
  149.     else if (fd <= maxsysfd) {
  150.         saveifp = stio->ifp;
  151.         saveofp = stio->ofp;
  152.         savetype = stio->type;
  153.         result = 0;
  154.     }
  155.     else if (stio->type == '|')
  156.         result = mypclose(stio->ifp);
  157.     else if (stio->ifp != stio->ofp) {
  158.         if (stio->ofp) {
  159.         result = fclose(stio->ofp);
  160.         fclose(stio->ifp);    /* clear stdio, fd already closed */
  161.         }
  162.         else
  163.         result = fclose(stio->ifp);
  164.     }
  165.     else
  166.         result = fclose(stio->ifp);
  167.     if (result == EOF && fd > maxsysfd)
  168.         fprintf(stderr,"Warning: unable to close filehandle %s properly.\n",
  169.           stab_name(stab));
  170.     stio->ofp = stio->ifp = Nullfp;
  171.     }
  172.     if (*name == '+' && len > 1 && name[len-1] != '|') {    /* scary */
  173.     mode[1] = *name++;
  174.     mode[2] = '\0';
  175.     --len;
  176.     writing = 1;
  177.     }
  178.     else  {
  179.     mode[1] = '\0';
  180.     }
  181.     stio->type = *name;
  182.     if (*name == '|') {
  183.     /*SUPPRESS 530*/
  184.     for (name++; isSPACE(*name); name++) ;
  185. #ifdef TAINT
  186.     taintenv();
  187.     taintproper("Insecure dependency in piped open");
  188. #endif
  189.     fp = mypopen(name,"w");
  190.     writing = 1;
  191.     }
  192.     else if (*name == '>') {
  193. #ifdef TAINT
  194.     taintproper("Insecure dependency in open");
  195. #endif
  196.     name++;
  197.     if (*name == '>') {
  198.         mode[0] = stio->type = 'a';
  199.         name++;
  200.     }
  201.     else
  202.         mode[0] = 'w';
  203.     writing = 1;
  204.     if (*name == '&') {
  205.       duplicity:
  206.         name++;
  207.         while (isSPACE(*name))
  208.         name++;
  209.         if (isDIGIT(*name))
  210.         fd = atoi(name);
  211.         else {
  212.         stab = stabent(name,FALSE);
  213.         if (!stab || !stab_io(stab)) {
  214. #ifdef EINVAL
  215.             errno = EINVAL;
  216. #endif
  217.             goto say_false;
  218.         }
  219.         if (stab_io(stab) && stab_io(stab)->ifp) {
  220.             fd = fileno(stab_io(stab)->ifp);
  221.             if (stab_io(stab)->type == 's')
  222.             stio->type = 's';
  223.         }
  224.         else
  225.             fd = -1;
  226.         }
  227.         if (!(fp = fdopen(fd = dup(fd),mode))) {
  228.         close(fd);
  229.         }
  230.     }
  231.     else {
  232.         while (isSPACE(*name))
  233.         name++;
  234.         if (strEQ(name,"-")) {
  235.         fp = stdout;
  236.         stio->type = '-';
  237.         }
  238.         else  {
  239.         fp = fopen(name,mode);
  240.         }
  241.     }
  242.     }
  243.     else {
  244.     if (*name == '<') {
  245.         mode[0] = 'r';
  246.         name++;
  247.         while (isSPACE(*name))
  248.         name++;
  249.         if (*name == '&')
  250.         goto duplicity;
  251.         if (strEQ(name,"-")) {
  252.         fp = stdin;
  253.         stio->type = '-';
  254.         }
  255.         else
  256.         fp = fopen(name,mode);
  257.     }
  258.     else if (name[len-1] == '|') {
  259. #ifdef TAINT
  260.         taintenv();
  261.         taintproper("Insecure dependency in piped open");
  262. #endif
  263.         name[--len] = '\0';
  264.         while (len && isSPACE(name[len-1]))
  265.         name[--len] = '\0';
  266.         /*SUPPRESS 530*/
  267.         for (; isSPACE(*name); name++) ;
  268.         fp = mypopen(name,"r");
  269.         stio->type = '|';
  270.     }
  271.     else {
  272.         stio->type = '<';
  273.         /*SUPPRESS 530*/
  274.         for (; isSPACE(*name); name++) ;
  275.         if (strEQ(name,"-")) {
  276.         fp = stdin;
  277.         stio->type = '-';
  278.         }
  279.         else
  280.         fp = fopen(name,"r");
  281.     }
  282.     }
  283.     Safefree(myname);
  284.     if (!fp)
  285.     goto say_false;
  286.     if (stio->type &&
  287.       stio->type != '|' && stio->type != '-') {
  288.     if (fstat(fileno(fp),&statbuf) < 0) {
  289.         (void)fclose(fp);
  290.         goto say_false;
  291.     }
  292.     if (S_ISSOCK(statbuf.st_mode))
  293.         stio->type = 's';    /* in case a socket was passed in to us */
  294. #ifdef HAS_SOCKET
  295.     else if (
  296. #ifdef S_IFMT
  297.         !(statbuf.st_mode & S_IFMT)
  298. #else
  299.         !statbuf.st_mode
  300. #endif
  301.     ) {
  302.         if (getsockname(fileno(fp), tokenbuf, 0) >= 0 || errno != ENOTSOCK)
  303.         stio->type = 's'; /* some OS's return 0 on fstat()ed socket */
  304.                 /* but some return 0 for streams too, sigh */
  305.     }
  306. #endif
  307.     }
  308.     if (saveifp) {        /* must use old fp? */
  309.     fd = fileno(saveifp);
  310.     if (saveofp) {
  311.         fflush(saveofp);        /* emulate fclose() */
  312.         if (saveofp != saveifp) {    /* was a socket? */
  313.         fclose(saveofp);
  314.         if (fd > 2)
  315.             Safefree(saveofp);
  316.         }
  317.     }
  318.     if (fd != fileno(fp)) {
  319.         dup2(fileno(fp), fd);
  320.         fclose(fp);
  321.     }
  322.     fp = saveifp;
  323.     }
  324. #if defined(HAS_FCNTL) && defined(F_SETFD)
  325.     fd = fileno(fp);
  326.     fcntl(fd,F_SETFD,fd > maxsysfd);
  327. #endif
  328.     stio->ifp = fp;
  329.     if (writing) {
  330.     if (stio->type == 's'
  331.       || (stio->type == '>' && S_ISCHR(statbuf.st_mode)) ) {
  332.         if (!(stio->ofp = fdopen(fileno(fp),"w"))) {
  333.         fclose(fp);
  334.         stio->ifp = Nullfp;
  335.         goto say_false;
  336.         }
  337.     }
  338.     else
  339.         stio->ofp = fp;
  340.     }
  341.     return TRUE;
  342.  
  343. say_false:
  344.     stio->ifp = saveifp;
  345.     stio->ofp = saveofp;
  346.     stio->type = savetype;
  347.     return FALSE;
  348. }
  349.  
  350. FILE *
  351. nextargv(stab)
  352. register STAB *stab;
  353. {
  354.     register STR *str;
  355. #ifndef FLEXFILENAMES
  356.     int filedev;
  357.     int fileino;
  358. #endif
  359.     int fileuid;
  360.     int filegid;
  361.     static int filemode = 0;
  362.     static int lastfd;
  363.     static char *oldname;
  364.  
  365.     if (!argvoutstab)
  366.     argvoutstab = stabent("ARGVOUT",TRUE);
  367.     if (filemode & (S_ISUID|S_ISGID)) {
  368.     fflush(stab_io(argvoutstab)->ifp);  /* chmod must follow last write */
  369. #ifdef HAS_FCHMOD
  370.     (void)fchmod(lastfd,filemode);
  371. #else
  372.     (void)chmod(oldname,filemode);
  373. #endif
  374.     }
  375.     filemode = 0;
  376.     while (alen(stab_xarray(stab)) >= 0) {
  377.     str = ashift(stab_xarray(stab));
  378.     str_sset(stab_val(stab),str);
  379.     STABSET(stab_val(stab));
  380.     oldname = str_get(stab_val(stab));
  381.     if (do_open(stab,oldname,stab_val(stab)->str_cur)) {
  382.         if (inplace) {
  383. #ifdef TAINT
  384.         taintproper("Insecure dependency in inplace open");
  385. #endif
  386.         if (strEQ(oldname,"-")) {
  387.             str_free(str);
  388.             defoutstab = stabent("STDOUT",TRUE);
  389.             return stab_io(stab)->ifp;
  390.         }
  391. #ifndef FLEXFILENAMES
  392.         filedev = statbuf.st_dev;
  393.         fileino = statbuf.st_ino;
  394. #endif
  395.         filemode = statbuf.st_mode;
  396.         fileuid = statbuf.st_uid;
  397.         filegid = statbuf.st_gid;
  398.         if (!S_ISREG(filemode)) {
  399.             warn("Can't do inplace edit: %s is not a regular file",
  400.               oldname );
  401.             do_close(stab,FALSE);
  402.             str_free(str);
  403.             continue;
  404.         }
  405.         if (*inplace) {
  406. #ifdef SUFFIX
  407.             add_suffix(str,inplace);
  408. #else
  409.             str_cat(str,inplace);
  410. #endif
  411. #ifndef FLEXFILENAMES
  412.             if (stat(str->str_ptr,&statbuf) >= 0
  413.               && statbuf.st_dev == filedev
  414.               && statbuf.st_ino == fileino ) {
  415.             warn("Can't do inplace edit: %s > 14 characters",
  416.               str->str_ptr );
  417.             do_close(stab,FALSE);
  418.             str_free(str);
  419.             continue;
  420.             }
  421. #endif
  422. #ifdef HAS_RENAME
  423. #ifndef MSDOS
  424.             if (rename(oldname,str->str_ptr) < 0) {
  425.             warn("Can't rename %s to %s: %s, skipping file",
  426.               oldname, str->str_ptr, strerror(errno) );
  427.             do_close(stab,FALSE);
  428.             str_free(str);
  429.             continue;
  430.             }
  431. #else
  432.             do_close(stab,FALSE);
  433.             (void)unlink(str->str_ptr);
  434.             (void)rename(oldname,str->str_ptr);
  435.             do_open(stab,str->str_ptr,stab_val(stab)->str_cur);
  436. #endif /* MSDOS */
  437. #else
  438.             (void)UNLINK(str->str_ptr);
  439.             if (link(oldname,str->str_ptr) < 0) {
  440.             warn("Can't rename %s to %s: %s, skipping file",
  441.               oldname, str->str_ptr, strerror(errno) );
  442.             do_close(stab,FALSE);
  443.             str_free(str);
  444.             continue;
  445.             }
  446.             (void)UNLINK(oldname);
  447. #endif
  448.         }
  449.         else {
  450. #ifndef MSDOS
  451.             if (UNLINK(oldname) < 0) {
  452.             warn("Can't rename %s to %s: %s, skipping file",
  453.               oldname, str->str_ptr, strerror(errno) );
  454.             do_close(stab,FALSE);
  455.             str_free(str);
  456.             continue;
  457.             }
  458. #else
  459.             fatal("Can't do inplace edit without backup");
  460. #endif
  461.         }
  462.  
  463.         str_nset(str,">",1);
  464.         str_cat(str,oldname);
  465.         errno = 0;        /* in case sprintf set errno */
  466.         if (!do_open(argvoutstab,str->str_ptr,str->str_cur)) {
  467.             warn("Can't do inplace edit on %s: %s",
  468.               oldname, strerror(errno) );
  469.             do_close(stab,FALSE);
  470.             str_free(str);
  471.             continue;
  472.         }
  473.         defoutstab = argvoutstab;
  474.         lastfd = fileno(stab_io(argvoutstab)->ifp);
  475.         (void)fstat(lastfd,&statbuf);
  476. #ifdef HAS_FCHMOD
  477.         (void)fchmod(lastfd,filemode);
  478. #else
  479.         (void)chmod(oldname,filemode);
  480. #endif
  481.         if (fileuid != statbuf.st_uid || filegid != statbuf.st_gid) {
  482. #ifdef HAS_FCHOWN
  483.             (void)fchown(lastfd,fileuid,filegid);
  484. #else
  485. #ifdef HAS_CHOWN
  486.             (void)chown(oldname,fileuid,filegid);
  487. #endif
  488. #endif
  489.         }
  490.         }
  491.         str_free(str);
  492.         return stab_io(stab)->ifp;
  493.     }
  494.     else
  495.         fprintf(stderr,"Can't open %s: %s\n",str_get(str), strerror(errno));
  496.     str_free(str);
  497.     }
  498.     if (inplace) {
  499.     (void)do_close(argvoutstab,FALSE);
  500.     defoutstab = stabent("STDOUT",TRUE);
  501.     }
  502.     return Nullfp;
  503. }
  504.  
  505. #ifdef HAS_PIPE
  506. void
  507. do_pipe(str, rstab, wstab)
  508. STR *str;
  509. STAB *rstab;
  510. STAB *wstab;
  511. {
  512.     register STIO *rstio;
  513.     register STIO *wstio;
  514.     int fd[2];
  515.  
  516.     if (!rstab)
  517.     goto badexit;
  518.     if (!wstab)
  519.     goto badexit;
  520.  
  521.     rstio = stab_io(rstab);
  522.     wstio = stab_io(wstab);
  523.  
  524.     if (!rstio)
  525.     rstio = stab_io(rstab) = stio_new();
  526.     else if (rstio->ifp)
  527.     do_close(rstab,FALSE);
  528.     if (!wstio)
  529.     wstio = stab_io(wstab) = stio_new();
  530.     else if (wstio->ifp)
  531.     do_close(wstab,FALSE);
  532.  
  533.     if (pipe(fd) < 0)
  534.     goto badexit;
  535.     rstio->ifp = fdopen(fd[0], "r");
  536.     wstio->ofp = fdopen(fd[1], "w");
  537.     wstio->ifp = wstio->ofp;
  538.     rstio->type = '<';
  539.     wstio->type = '>';
  540.     if (!rstio->ifp || !wstio->ofp) {
  541.     if (rstio->ifp) fclose(rstio->ifp);
  542.     else close(fd[0]);
  543.     if (wstio->ofp) fclose(wstio->ofp);
  544.     else close(fd[1]);
  545.     goto badexit;
  546.     }
  547.  
  548.     str_sset(str,&str_yes);
  549.     return;
  550.  
  551. badexit:
  552.     str_sset(str,&str_undef);
  553.     return;
  554. }
  555. #endif
  556.  
  557. bool
  558. do_close(stab,explicit)
  559. STAB *stab;
  560. bool explicit;
  561. {
  562.     bool retval = FALSE;
  563.     register STIO *stio;
  564.     int status;
  565.  
  566.     if (!stab)
  567.     stab = argvstab;
  568.     if (!stab) {
  569.     errno = EBADF;
  570.     return FALSE;
  571.     }
  572.     stio = stab_io(stab);
  573.     if (!stio) {        /* never opened */
  574.     if (dowarn && explicit)
  575.         warn("Close on unopened file <%s>",stab_name(stab));
  576.     return FALSE;
  577.     }
  578.     if (stio->ifp) {
  579.     if (stio->type == '|') {
  580.         status = mypclose(stio->ifp);
  581.         retval = (status == 0);
  582.         statusvalue = (unsigned short)status & 0xffff;
  583.     }
  584.     else if (stio->type == '-')
  585.         retval = TRUE;
  586.     else {
  587.         if (stio->ofp && stio->ofp != stio->ifp) {        /* a socket */
  588.         retval = (fclose(stio->ofp) != EOF);
  589.         fclose(stio->ifp);    /* clear stdio, fd already closed */
  590.         }
  591.         else
  592.         retval = (fclose(stio->ifp) != EOF);
  593.     }
  594.     stio->ofp = stio->ifp = Nullfp;
  595.     }
  596.     if (explicit)
  597.     stio->lines = 0;
  598.     stio->type = ' ';
  599.     return retval;
  600. }
  601.  
  602. bool
  603. do_eof(stab)
  604. STAB *stab;
  605. {
  606.     register STIO *stio;
  607.     int ch;
  608.  
  609.     if (!stab) {            /* eof() */
  610.     if (argvstab)
  611.         stio = stab_io(argvstab);
  612.     else
  613.         return TRUE;
  614.     }
  615.     else
  616.     stio = stab_io(stab);
  617.  
  618.     if (!stio)
  619.     return TRUE;
  620.  
  621.     while (stio->ifp) {
  622.  
  623. #ifdef STDSTDIO            /* (the code works without this) */
  624.     if (stio->ifp->_cnt > 0)    /* cheat a little, since */
  625.         return FALSE;        /* this is the most usual case */
  626. #endif
  627.  
  628.     ch = getc(stio->ifp);
  629.     if (ch != EOF) {
  630.         (void)ungetc(ch, stio->ifp);
  631.         return FALSE;
  632.     }
  633. #ifdef STDSTDIO
  634.     if (stio->ifp->_cnt < -1)
  635.         stio->ifp->_cnt = -1;
  636. #endif
  637.     if (!stab) {            /* not necessarily a real EOF yet? */
  638.         if (!nextargv(argvstab))    /* get another fp handy */
  639.         return TRUE;
  640.     }
  641.     else
  642.         return TRUE;        /* normal fp, definitely end of file */
  643.     }
  644.     return TRUE;
  645. }
  646.  
  647. long
  648. do_tell(stab)
  649. STAB *stab;
  650. {
  651.     register STIO *stio;
  652.  
  653.     if (!stab)
  654.     goto phooey;
  655.  
  656.     stio = stab_io(stab);
  657.     if (!stio || !stio->ifp)
  658.     goto phooey;
  659.  
  660.     if (feof(stio->ifp))
  661.     (void)fseek (stio->ifp, 0L, 2);        /* ultrix 1.2 workaround */
  662.  
  663.     return ftell(stio->ifp);
  664.  
  665. phooey:
  666.     if (dowarn)
  667.     warn("tell() on unopened file");
  668.     errno = EBADF;
  669.     return -1L;
  670. }
  671.  
  672. bool
  673. do_seek(stab, pos, whence)
  674. STAB *stab;
  675. long pos;
  676. int whence;
  677. {
  678.     register STIO *stio;
  679.  
  680.     if (!stab)
  681.     goto nuts;
  682.  
  683.     stio = stab_io(stab);
  684.     if (!stio || !stio->ifp)
  685.     goto nuts;
  686.  
  687.     if (feof(stio->ifp))
  688.     (void)fseek (stio->ifp, 0L, 2);        /* ultrix 1.2 workaround */
  689.  
  690.     return fseek(stio->ifp, pos, whence) >= 0;
  691.  
  692. nuts:
  693.     if (dowarn)
  694.     warn("seek() on unopened file");
  695.     errno = EBADF;
  696.     return FALSE;
  697. }
  698.  
  699. int
  700. do_ctl(optype,stab,func,argstr)
  701. int optype;
  702. STAB *stab;
  703. int func;
  704. STR *argstr;
  705. {
  706.     register STIO *stio;
  707.     register char *s;
  708.     int retval;
  709.  
  710.     if (!stab || !argstr || !(stio = stab_io(stab)) || !stio->ifp) {
  711.     errno = EBADF;    /* well, sort of... */
  712.     return -1;
  713.     }
  714.  
  715.     if (argstr->str_pok || !argstr->str_nok) {
  716.     if (!argstr->str_pok)
  717.         s = str_get(argstr);
  718.  
  719. #ifdef IOCPARM_MASK
  720. #ifndef IOCPARM_LEN
  721. #define IOCPARM_LEN(x)  (((x) >> 16) & IOCPARM_MASK)
  722. #endif
  723. #endif
  724. #ifdef IOCPARM_LEN
  725.     retval = IOCPARM_LEN(func);    /* on BSDish systes we're safe */
  726. #else
  727.     retval = 256;            /* otherwise guess at what's safe */
  728. #endif
  729.     if (argstr->str_cur < retval) {
  730.         Str_Grow(argstr,retval+1);
  731.         argstr->str_cur = retval;
  732.     }
  733.  
  734.     s = argstr->str_ptr;
  735.     s[argstr->str_cur] = 17;    /* a little sanity check here */
  736.     }
  737.     else {
  738.     retval = (int)str_gnum(argstr);
  739. #ifdef MSDOS
  740.     s = (char*)(long)retval;        /* ouch */
  741. #else
  742.     s = (char*)retval;        /* ouch */
  743. #endif
  744.     }
  745.  
  746. #ifndef lint
  747.     if (optype == O_IOCTL)
  748.     retval = ioctl(fileno(stio->ifp), func, s);
  749.     else
  750. #ifdef MSDOS
  751.     fatal("fcntl is not implemented");
  752. #else
  753. #ifdef HAS_FCNTL
  754.     retval = fcntl(fileno(stio->ifp), func, s);
  755. #else
  756.     fatal("fcntl is not implemented");
  757. #endif
  758. #endif
  759. #else /* lint */
  760.     retval = 0;
  761. #endif /* lint */
  762.  
  763.     if (argstr->str_pok) {
  764.     if (s[argstr->str_cur] != 17)
  765.         fatal("Return value overflowed string");
  766.     s[argstr->str_cur] = 0;        /* put our null back */
  767.     }
  768.     return retval;
  769. }
  770.  
  771. int
  772. do_stat(str,arg,gimme,arglast)
  773. STR *str;
  774. register ARG *arg;
  775. int gimme;
  776. int *arglast;
  777. {
  778.     register ARRAY *ary = stack;
  779.     register int sp = arglast[0] + 1;
  780.     int max = 13;
  781.  
  782.     if ((arg[1].arg_type & A_MASK) == A_WORD) {
  783.     tmpstab = arg[1].arg_ptr.arg_stab;
  784.     if (tmpstab != defstab) {
  785.         laststype = O_STAT;
  786.         statstab = tmpstab;
  787.         str_set(statname,"");
  788.         if (!stab_io(tmpstab) || !stab_io(tmpstab)->ifp ||
  789.           fstat(fileno(stab_io(tmpstab)->ifp),&statcache) < 0) {
  790.         max = 0;
  791.         laststatval = -1;
  792.         }
  793.     }
  794.     else if (laststatval < 0)
  795.         max = 0;
  796.     }
  797.     else {
  798.     str_set(statname,str_get(ary->ary_array[sp]));
  799.     statstab = Nullstab;
  800. #ifdef HAS_LSTAT
  801.     laststype = arg->arg_type;
  802.     if (arg->arg_type == O_LSTAT)
  803.         laststatval = lstat(str_get(statname),&statcache);
  804.     else
  805. #endif
  806.         laststatval = stat(str_get(statname),&statcache);
  807.     if (laststatval < 0)
  808.         max = 0;
  809.     }
  810.  
  811.     if (gimme != G_ARRAY) {
  812.     if (max)
  813.         str_sset(str,&str_yes);
  814.     else
  815.         str_sset(str,&str_undef);
  816.     STABSET(str);
  817.     ary->ary_array[sp] = str;
  818.     return sp;
  819.     }
  820.     sp--;
  821.     if (max) {
  822. #ifndef lint
  823.     (void)astore(ary,++sp,
  824.       str_2mortal(str_nmake((double)statcache.st_dev)));
  825.     (void)astore(ary,++sp,
  826.       str_2mortal(str_nmake((double)statcache.st_ino)));
  827.     (void)astore(ary,++sp,
  828.       str_2mortal(str_nmake((double)statcache.st_mode)));
  829.     (void)astore(ary,++sp,
  830.       str_2mortal(str_nmake((double)statcache.st_nlink)));
  831.     (void)astore(ary,++sp,
  832.       str_2mortal(str_nmake((double)statcache.st_uid)));
  833.     (void)astore(ary,++sp,
  834.       str_2mortal(str_nmake((double)statcache.st_gid)));
  835.     (void)astore(ary,++sp,
  836.       str_2mortal(str_nmake((double)statcache.st_rdev)));
  837.     (void)astore(ary,++sp,
  838.       str_2mortal(str_nmake((double)statcache.st_size)));
  839.     (void)astore(ary,++sp,
  840.       str_2mortal(str_nmake((double)statcache.st_atime)));
  841.     (void)astore(ary,++sp,
  842.       str_2mortal(str_nmake((double)statcache.st_mtime)));
  843.     (void)astore(ary,++sp,
  844.       str_2mortal(str_nmake((double)statcache.st_ctime)));
  845. #ifdef STATBLOCKS
  846.     (void)astore(ary,++sp,
  847.       str_2mortal(str_nmake((double)statcache.st_blksize)));
  848.     (void)astore(ary,++sp,
  849.       str_2mortal(str_nmake((double)statcache.st_blocks)));
  850. #else
  851.     (void)astore(ary,++sp,
  852.       str_2mortal(str_make("",0)));
  853.     (void)astore(ary,++sp,
  854.       str_2mortal(str_make("",0)));
  855. #endif
  856. #ifdef sprite
  857.     (void)astore(ary,++sp,
  858.       str_2mortal(str_nmake((double)statcache.st_serverID)));
  859.     (void)astore(ary,++sp,
  860.       str_2mortal(str_nmake((double)statcache.st_version)));
  861.     (void)astore(ary,++sp,
  862.       str_2mortal(str_nmake((double)statcache.st_userType)));
  863.     (void)astore(ary,++sp,
  864.       str_2mortal(str_nmake((double)statcache.st_devServerID)));
  865. #endif
  866.  
  867. #else /* lint */
  868.     (void)astore(ary,++sp,str_nmake(0.0));
  869. #endif /* lint */
  870.     }
  871.     return sp;
  872. }
  873.  
  874. #if !defined(HAS_TRUNCATE) && !defined(HAS_CHSIZE) && defined(F_FREESP)
  875.     /* code courtesy of William Kucharski */
  876. #define HAS_CHSIZE
  877.  
  878. int chsize(fd, length)
  879. int fd;            /* file descriptor */
  880. off_t length;        /* length to set file to */
  881. {
  882.     extern long lseek();
  883.     struct flock fl;
  884.     struct stat filebuf;
  885.  
  886.     if (fstat(fd, &filebuf) < 0)
  887.     return -1;
  888.  
  889.     if (filebuf.st_size < length) {
  890.  
  891.     /* extend file length */
  892.  
  893.     if ((lseek(fd, (length - 1), 0)) < 0)
  894.         return -1;
  895.  
  896.     /* write a "0" byte */
  897.  
  898.     if ((write(fd, "", 1)) != 1)
  899.         return -1;
  900.     }
  901.     else {
  902.     /* truncate length */
  903.  
  904.     fl.l_whence = 0;
  905.     fl.l_len = 0;
  906.     fl.l_start = length;
  907.     fl.l_type = F_WRLCK;    /* write lock on file space */
  908.  
  909.     /*
  910.     * This relies on the UNDOCUMENTED F_FREESP argument to
  911.     * fcntl(2), which truncates the file so that it ends at the
  912.     * position indicated by fl.l_start.
  913.     *
  914.     * Will minor miracles never cease?
  915.     */
  916.  
  917.     if (fcntl(fd, F_FREESP, &fl) < 0)
  918.         return -1;
  919.  
  920.     }
  921.  
  922.     return 0;
  923. }
  924. #endif /* F_FREESP */
  925.  
  926. int                    /*SUPPRESS 590*/
  927. do_truncate(str,arg,gimme,arglast)
  928. STR *str;
  929. register ARG *arg;
  930. int gimme;
  931. int *arglast;
  932. {
  933.     register ARRAY *ary = stack;
  934.     register int sp = arglast[0] + 1;
  935.     off_t len = (off_t)str_gnum(ary->ary_array[sp+1]);
  936.     int result = 1;
  937.     STAB *tmpstab;
  938.  
  939. #if defined(HAS_TRUNCATE) || defined(HAS_CHSIZE)
  940. #ifdef HAS_TRUNCATE
  941.     if ((arg[1].arg_type & A_MASK) == A_WORD) {
  942.     tmpstab = arg[1].arg_ptr.arg_stab;
  943.     if (!stab_io(tmpstab) || !stab_io(tmpstab)->ifp ||
  944.       ftruncate(fileno(stab_io(tmpstab)->ifp), len) < 0)
  945.         result = 0;
  946.     }
  947.     else if (truncate(str_get(ary->ary_array[sp]), len) < 0)
  948.     result = 0;
  949. #else
  950.     if ((arg[1].arg_type & A_MASK) == A_WORD) {
  951.     tmpstab = arg[1].arg_ptr.arg_stab;
  952.     if (!stab_io(tmpstab) || !stab_io(tmpstab)->ifp ||
  953.       chsize(fileno(stab_io(tmpstab)->ifp), len) < 0)
  954.         result = 0;
  955.     }
  956.     else {
  957.     int tmpfd;
  958.  
  959.     if ((tmpfd = open(str_get(ary->ary_array[sp]), 0)) < 0)
  960.         result = 0;
  961.     else {
  962.         if (chsize(tmpfd, len) < 0)
  963.         result = 0;
  964.         close(tmpfd);
  965.     }
  966.     }
  967. #endif
  968.  
  969.     if (result)
  970.     str_sset(str,&str_yes);
  971.     else
  972.     str_sset(str,&str_undef);
  973.     STABSET(str);
  974.     ary->ary_array[sp] = str;
  975.     return sp;
  976. #else
  977.     fatal("truncate not implemented");
  978. #endif
  979. }
  980.  
  981. int
  982. looks_like_number(str)
  983. STR *str;
  984. {
  985.     register char *s;
  986.     register char *send;
  987.  
  988.     if (!str->str_pok)
  989.     return TRUE;
  990.     s = str->str_ptr; 
  991.     send = s + str->str_cur;
  992.     while (isSPACE(*s))
  993.     s++;
  994.     if (s >= send)
  995.     return FALSE;
  996.     if (*s == '+' || *s == '-')
  997.     s++;
  998.     while (isDIGIT(*s))
  999.     s++;
  1000.     if (s == send)
  1001.     return TRUE;
  1002.     if (*s == '.') 
  1003.     s++;
  1004.     else if (s == str->str_ptr)
  1005.     return FALSE;
  1006.     while (isDIGIT(*s))
  1007.     s++;
  1008.     if (s == send)
  1009.     return TRUE;
  1010.     if (*s == 'e' || *s == 'E') {
  1011.     s++;
  1012.     if (*s == '+' || *s == '-')
  1013.         s++;
  1014.     while (isDIGIT(*s))
  1015.         s++;
  1016.     }
  1017.     while (isSPACE(*s))
  1018.     s++;
  1019.     if (s >= send)
  1020.     return TRUE;
  1021.     return FALSE;
  1022. }
  1023.  
  1024. bool
  1025. do_print(str,fp)
  1026. register STR *str;
  1027. FILE *fp;
  1028. {
  1029.     register char *tmps;
  1030.  
  1031.     if (!fp) {
  1032.     if (dowarn)
  1033.         warn("print to unopened file");
  1034.     errno = EBADF;
  1035.     return FALSE;
  1036.     }
  1037.     if (!str)
  1038.     return TRUE;
  1039.     if (ofmt &&
  1040.       ((str->str_nok && str->str_u.str_nval != 0.0)
  1041.        || (looks_like_number(str) && str_gnum(str) != 0.0) ) ) {
  1042.     fprintf(fp, ofmt, str->str_u.str_nval);
  1043.     return !ferror(fp);
  1044.     }
  1045.     else {
  1046.     tmps = str_get(str);
  1047.     if (*tmps == 'S' && tmps[1] == 't' && tmps[2] == 'B' && tmps[3] == '\0'
  1048.       && str->str_cur == sizeof(STBP) && strlen(tmps) < str->str_cur) {
  1049.         STR *tmpstr = str_mortal(&str_undef);
  1050.         stab_fullname(tmpstr,((STAB*)str));/* a stab value, be nice */
  1051.         str = tmpstr;
  1052.         tmps = str->str_ptr;
  1053.         putc('*',fp);
  1054.     }
  1055.     if (str->str_cur && (fwrite(tmps,1,str->str_cur,fp) == 0 || ferror(fp)))
  1056.         return FALSE;
  1057.     }
  1058.     return TRUE;
  1059. }
  1060.  
  1061. bool
  1062. do_aprint(arg,fp,arglast)
  1063. register ARG *arg;
  1064. register FILE *fp;
  1065. int *arglast;
  1066. {
  1067.     register STR **st = stack->ary_array;
  1068.     register int sp = arglast[1];
  1069.     register int retval;
  1070.     register int items = arglast[2] - sp;
  1071.  
  1072.     if (!fp) {
  1073.     if (dowarn)
  1074.         warn("print to unopened file");
  1075.     errno = EBADF;
  1076.     return FALSE;
  1077.     }
  1078.     st += ++sp;
  1079.     if (arg->arg_type == O_PRTF) {
  1080.     do_sprintf(arg->arg_ptr.arg_str,items,st);
  1081.     retval = do_print(arg->arg_ptr.arg_str,fp);
  1082.     }
  1083.     else {
  1084.     retval = (items <= 0);
  1085.     for (; items > 0; items--,st++) {
  1086.         if (retval && ofslen) {
  1087.         if (fwrite(ofs, 1, ofslen, fp) == 0 || ferror(fp)) {
  1088.             retval = FALSE;
  1089.             break;
  1090.         }
  1091.         }
  1092.         if (!(retval = do_print(*st, fp)))
  1093.         break;
  1094.     }
  1095.     if (retval && orslen)
  1096.         if (fwrite(ors, 1, orslen, fp) == 0 || ferror(fp))
  1097.         retval = FALSE;
  1098.     }
  1099.     return retval;
  1100. }
  1101.  
  1102. int
  1103. mystat(arg,str)
  1104. ARG *arg;
  1105. STR *str;
  1106. {
  1107.     STIO *stio;
  1108.  
  1109.     if (arg[1].arg_type & A_DONT) {
  1110.     stio = stab_io(arg[1].arg_ptr.arg_stab);
  1111.     if (stio && stio->ifp) {
  1112.         statstab = arg[1].arg_ptr.arg_stab;
  1113.         str_set(statname,"");
  1114.         laststype = O_STAT;
  1115.         return (laststatval = fstat(fileno(stio->ifp), &statcache));
  1116.     }
  1117.     else {
  1118.         if (arg[1].arg_ptr.arg_stab == defstab)
  1119.         return laststatval;
  1120.         if (dowarn)
  1121.         warn("Stat on unopened file <%s>",
  1122.           stab_name(arg[1].arg_ptr.arg_stab));
  1123.         statstab = Nullstab;
  1124.         str_set(statname,"");
  1125.         return (laststatval = -1);
  1126.     }
  1127.     }
  1128.     else {
  1129.     statstab = Nullstab;
  1130.     str_set(statname,str_get(str));
  1131.     laststype = O_STAT;
  1132.     return (laststatval = stat(str_get(str),&statcache));
  1133.     }
  1134. }
  1135.  
  1136. int
  1137. mylstat(arg,str)
  1138. ARG *arg;
  1139. STR *str;
  1140. {
  1141.     if (arg[1].arg_type & A_DONT) {
  1142.     if (arg[1].arg_ptr.arg_stab == defstab) {
  1143.         if (laststype != O_LSTAT)
  1144.         fatal("The stat preceding -l _ wasn't an lstat");
  1145.         return laststatval;
  1146.     }
  1147.     fatal("You can't use -l on a filehandle");
  1148.     }
  1149.  
  1150.     laststype = O_LSTAT;
  1151.     statstab = Nullstab;
  1152.     str_set(statname,str_get(str));
  1153. #ifdef HAS_LSTAT
  1154.     return (laststatval = lstat(str_get(str),&statcache));
  1155. #else
  1156.     return (laststatval = stat(str_get(str),&statcache));
  1157. #endif
  1158. }
  1159.  
  1160. STR *
  1161. do_fttext(arg,str)
  1162. register ARG *arg;
  1163. STR *str;
  1164. {
  1165.     int i;
  1166.     int len;
  1167.     int odd = 0;
  1168.     STDCHAR tbuf[512];
  1169.     register STDCHAR *s;
  1170.     register STIO *stio;
  1171.  
  1172.     if (arg[1].arg_type & A_DONT) {
  1173.     if (arg[1].arg_ptr.arg_stab == defstab) {
  1174.         if (statstab)
  1175.         stio = stab_io(statstab);
  1176.         else {
  1177.         str = statname;
  1178.         goto really_filename;
  1179.         }
  1180.     }
  1181.     else {
  1182.         statstab = arg[1].arg_ptr.arg_stab;
  1183.         str_set(statname,"");
  1184.         stio = stab_io(statstab);
  1185.     }
  1186.     if (stio && stio->ifp) {
  1187. #ifdef STDSTDIO
  1188.         fstat(fileno(stio->ifp),&statcache);
  1189.         if (S_ISDIR(statcache.st_mode))    /* handle NFS glitch */
  1190.         return arg->arg_type == O_FTTEXT ? &str_no : &str_yes;
  1191.         if (stio->ifp->_cnt <= 0) {
  1192.         i = getc(stio->ifp);
  1193.         if (i != EOF)
  1194.             (void)ungetc(i,stio->ifp);
  1195.         }
  1196.         if (stio->ifp->_cnt <= 0)    /* null file is anything */
  1197.         return &str_yes;
  1198.         len = stio->ifp->_cnt + (stio->ifp->_ptr - stio->ifp->_base);
  1199.         s = stio->ifp->_base;
  1200. #else
  1201.         fatal("-T and -B not implemented on filehandles");
  1202. #endif
  1203.     }
  1204.     else {
  1205.         if (dowarn)
  1206.         warn("Test on unopened file <%s>",
  1207.           stab_name(arg[1].arg_ptr.arg_stab));
  1208.         errno = EBADF;
  1209.         return &str_undef;
  1210.     }
  1211.     }
  1212.     else {
  1213.     statstab = Nullstab;
  1214.     str_set(statname,str_get(str));
  1215.       really_filename:
  1216.     i = open(str_get(str),0);
  1217.     if (i < 0)
  1218.         return &str_undef;
  1219.     fstat(i,&statcache);
  1220.     len = read(i,tbuf,512);
  1221.     (void)close(i);
  1222.     if (len <= 0) {
  1223.         if (S_ISDIR(statcache.st_mode) && arg->arg_type == O_FTTEXT)
  1224.         return &str_no;        /* special case NFS directories */
  1225.         return &str_yes;        /* null file is anything */
  1226.     }
  1227.     s = tbuf;
  1228.     }
  1229.  
  1230.     /* now scan s to look for textiness */
  1231.  
  1232.     for (i = 0; i < len; i++,s++) {
  1233.     if (!*s) {            /* null never allowed in text */
  1234.         odd += len;
  1235.         break;
  1236.     }
  1237.     else if (*s & 128)
  1238.         odd++;
  1239.     else if (*s < 32 &&
  1240.       *s != '\n' && *s != '\r' && *s != '\b' &&
  1241.       *s != '\t' && *s != '\f' && *s != 27)
  1242.         odd++;
  1243.     }
  1244.  
  1245.     if ((odd * 10 > len) == (arg->arg_type == O_FTTEXT)) /* allow 10% odd */
  1246.     return &str_no;
  1247.     else
  1248.     return &str_yes;
  1249. }
  1250.  
  1251. bool
  1252. do_aexec(really,arglast)
  1253. STR *really;
  1254. int *arglast;
  1255. {
  1256.     register STR **st = stack->ary_array;
  1257.     register int sp = arglast[1];
  1258.     register int items = arglast[2] - sp;
  1259.     register char **a;
  1260.     char **argv;
  1261.     char *tmps;
  1262.  
  1263.     if (items) {
  1264.     New(401,argv, items+1, char*);
  1265.     a = argv;
  1266.     for (st += ++sp; items > 0; items--,st++) {
  1267.         if (*st)
  1268.         *a++ = str_get(*st);
  1269.         else
  1270.         *a++ = "";
  1271.     }
  1272.     *a = Nullch;
  1273. #ifdef TAINT
  1274.     if (*argv[0] != '/')    /* will execvp use PATH? */
  1275.         taintenv();        /* testing IFS here is overkill, probably */
  1276. #endif
  1277.     if (really && *(tmps = str_get(really)))
  1278.         execvp(tmps,argv);
  1279.     else
  1280.         execvp(argv[0],argv);
  1281.     Safefree(argv);
  1282.     }
  1283.     return FALSE;
  1284. }
  1285.  
  1286. static char **Argv = Null(char **);
  1287. static char *Cmd = Nullch;
  1288.  
  1289. void
  1290. do_execfree()
  1291. {
  1292.     if (Argv) {
  1293.     Safefree(Argv);
  1294.     Argv = Null(char **);
  1295.     }
  1296.     if (Cmd) {
  1297.     Safefree(Cmd);
  1298.     Cmd = Nullch;
  1299.     }
  1300. }
  1301.  
  1302. bool
  1303. do_exec(cmd)
  1304. char *cmd;
  1305. {
  1306.     register char **a;
  1307.     register char *s;
  1308.     char flags[10];
  1309.  
  1310.     /* save an extra exec if possible */
  1311.  
  1312. #ifdef CSH
  1313.     if (strnEQ(cmd,cshname,cshlen) && strnEQ(cmd+cshlen," -c",3)) {
  1314.     strcpy(flags,"-c");
  1315.     s = cmd+cshlen+3;
  1316.     if (*s == 'f') {
  1317.         s++;
  1318.         strcat(flags,"f");
  1319.     }
  1320.     if (*s == ' ')
  1321.         s++;
  1322.     if (*s++ == '\'') {
  1323.         char *ncmd = s;
  1324.  
  1325.         while (*s)
  1326.         s++;
  1327.         if (s[-1] == '\n')
  1328.         *--s = '\0';
  1329.         if (s[-1] == '\'') {
  1330.         *--s = '\0';
  1331.         execl(cshname,"csh", flags,ncmd,(char*)0);
  1332.         *s = '\'';
  1333.         return FALSE;
  1334.         }
  1335.     }
  1336.     }
  1337. #endif /* CSH */
  1338.  
  1339.     /* see if there are shell metacharacters in it */
  1340.  
  1341.     /*SUPPRESS 530*/
  1342.     for (s = cmd; *s && isALPHA(*s); s++) ;    /* catch VAR=val gizmo */
  1343.     if (*s == '=')
  1344.     goto doshell;
  1345.     for (s = cmd; *s; s++) {
  1346.     if (*s != ' ' && !isALPHA(*s) && index("$&*(){}[]'\";\\|?<>~`\n",*s)) {
  1347.         if (*s == '\n' && !s[1]) {
  1348.         *s = '\0';
  1349.         break;
  1350.         }
  1351.       doshell:
  1352.         execl("/bin/sh","sh","-c",cmd,(char*)0);
  1353.         return FALSE;
  1354.     }
  1355.     }
  1356.     New(402,Argv, (s - cmd) / 2 + 2, char*);
  1357.     Cmd = nsavestr(cmd, s-cmd);
  1358.     a = Argv;
  1359.     for (s = Cmd; *s;) {
  1360.     while (*s && isSPACE(*s)) s++;
  1361.     if (*s)
  1362.         *(a++) = s;
  1363.     while (*s && !isSPACE(*s)) s++;
  1364.     if (*s)
  1365.         *s++ = '\0';
  1366.     }
  1367.     *a = Nullch;
  1368.     if (Argv[0]) {
  1369.     execvp(Argv[0],Argv);
  1370.     if (errno == ENOEXEC) {        /* for system V NIH syndrome */
  1371.         do_execfree();
  1372.         goto doshell;
  1373.     }
  1374.     }
  1375.     do_execfree();
  1376.     return FALSE;
  1377. }
  1378.  
  1379. #ifdef HAS_SOCKET
  1380. int
  1381. do_socket(stab, arglast)
  1382. STAB *stab;
  1383. int *arglast;
  1384. {
  1385.     register STR **st = stack->ary_array;
  1386.     register int sp = arglast[1];
  1387.     register STIO *stio;
  1388.     int domain, type, protocol, fd;
  1389.  
  1390.     if (!stab) {
  1391.     errno = EBADF;
  1392.     return FALSE;
  1393.     }
  1394.  
  1395.     stio = stab_io(stab);
  1396.     if (!stio)
  1397.     stio = stab_io(stab) = stio_new();
  1398.     else if (stio->ifp)
  1399.     do_close(stab,FALSE);
  1400.  
  1401.     domain = (int)str_gnum(st[++sp]);
  1402.     type = (int)str_gnum(st[++sp]);
  1403.     protocol = (int)str_gnum(st[++sp]);
  1404. #ifdef TAINT
  1405.     taintproper("Insecure dependency in socket");
  1406. #endif
  1407.     fd = socket(domain,type,protocol);
  1408.     if (fd < 0)
  1409.     return FALSE;
  1410.     stio->ifp = fdopen(fd, "r");    /* stdio gets confused about sockets */
  1411.     stio->ofp = fdopen(fd, "w");
  1412.     stio->type = 's';
  1413.     if (!stio->ifp || !stio->ofp) {
  1414.     if (stio->ifp) fclose(stio->ifp);
  1415.     if (stio->ofp) fclose(stio->ofp);
  1416.     if (!stio->ifp && !stio->ofp) close(fd);
  1417.     return FALSE;
  1418.     }
  1419.  
  1420.     return TRUE;
  1421. }
  1422.  
  1423. int
  1424. do_bind(stab, arglast)
  1425. STAB *stab;
  1426. int *arglast;
  1427. {
  1428.     register STR **st = stack->ary_array;
  1429.     register int sp = arglast[1];
  1430.     register STIO *stio;
  1431.     char *addr;
  1432.  
  1433.     if (!stab)
  1434.     goto nuts;
  1435.  
  1436.     stio = stab_io(stab);
  1437.     if (!stio || !stio->ifp)
  1438.     goto nuts;
  1439.  
  1440.     addr = str_get(st[++sp]);
  1441. #ifdef TAINT
  1442.     taintproper("Insecure dependency in bind");
  1443. #endif
  1444.     return bind(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
  1445.  
  1446. nuts:
  1447.     if (dowarn)
  1448.     warn("bind() on closed fd");
  1449.     errno = EBADF;
  1450.     return FALSE;
  1451.  
  1452. }
  1453.  
  1454. int
  1455. do_connect(stab, arglast)
  1456. STAB *stab;
  1457. int *arglast;
  1458. {
  1459.     register STR **st = stack->ary_array;
  1460.     register int sp = arglast[1];
  1461.     register STIO *stio;
  1462.     char *addr;
  1463.  
  1464.     if (!stab)
  1465.     goto nuts;
  1466.  
  1467.     stio = stab_io(stab);
  1468.     if (!stio || !stio->ifp)
  1469.     goto nuts;
  1470.  
  1471.     addr = str_get(st[++sp]);
  1472. #ifdef TAINT
  1473.     taintproper("Insecure dependency in connect");
  1474. #endif
  1475.     return connect(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
  1476.  
  1477. nuts:
  1478.     if (dowarn)
  1479.     warn("connect() on closed fd");
  1480.     errno = EBADF;
  1481.     return FALSE;
  1482.  
  1483. }
  1484.  
  1485. int
  1486. do_listen(stab, arglast)
  1487. STAB *stab;
  1488. int *arglast;
  1489. {
  1490.     register STR **st = stack->ary_array;
  1491.     register int sp = arglast[1];
  1492.     register STIO *stio;
  1493.     int backlog;
  1494.  
  1495.     if (!stab)
  1496.     goto nuts;
  1497.  
  1498.     stio = stab_io(stab);
  1499.     if (!stio || !stio->ifp)
  1500.     goto nuts;
  1501.  
  1502.     backlog = (int)str_gnum(st[++sp]);
  1503.     return listen(fileno(stio->ifp), backlog) >= 0;
  1504.  
  1505. nuts:
  1506.     if (dowarn)
  1507.     warn("listen() on closed fd");
  1508.     errno = EBADF;
  1509.     return FALSE;
  1510. }
  1511.  
  1512. void
  1513. do_accept(str, nstab, gstab)
  1514. STR *str;
  1515. STAB *nstab;
  1516. STAB *gstab;
  1517. {
  1518.     register STIO *nstio;
  1519.     register STIO *gstio;
  1520.     int len = sizeof buf;
  1521.     int fd;
  1522.  
  1523.     if (!nstab)
  1524.     goto badexit;
  1525.     if (!gstab)
  1526.     goto nuts;
  1527.  
  1528.     gstio = stab_io(gstab);
  1529.     nstio = stab_io(nstab);
  1530.  
  1531.     if (!gstio || !gstio->ifp)
  1532.     goto nuts;
  1533.     if (!nstio)
  1534.     nstio = stab_io(nstab) = stio_new();
  1535.     else if (nstio->ifp)
  1536.     do_close(nstab,FALSE);
  1537.  
  1538.     fd = accept(fileno(gstio->ifp),(struct sockaddr *)buf,&len);
  1539.     if (fd < 0)
  1540.     goto badexit;
  1541.     nstio->ifp = fdopen(fd, "r");
  1542.     nstio->ofp = fdopen(fd, "w");
  1543.     nstio->type = 's';
  1544.     if (!nstio->ifp || !nstio->ofp) {
  1545.     if (nstio->ifp) fclose(nstio->ifp);
  1546.     if (nstio->ofp) fclose(nstio->ofp);
  1547.     if (!nstio->ifp && !nstio->ofp) close(fd);
  1548.     goto badexit;
  1549.     }
  1550.  
  1551.     str_nset(str, buf, len);
  1552.     return;
  1553.  
  1554. nuts:
  1555.     if (dowarn)
  1556.     warn("accept() on closed fd");
  1557.     errno = EBADF;
  1558. badexit:
  1559.     str_sset(str,&str_undef);
  1560.     return;
  1561. }
  1562.  
  1563. int
  1564. do_shutdown(stab, arglast)
  1565. STAB *stab;
  1566. int *arglast;
  1567. {
  1568.     register STR **st = stack->ary_array;
  1569.     register int sp = arglast[1];
  1570.     register STIO *stio;
  1571.     int how;
  1572.  
  1573.     if (!stab)
  1574.     goto nuts;
  1575.  
  1576.     stio = stab_io(stab);
  1577.     if (!stio || !stio->ifp)
  1578.     goto nuts;
  1579.  
  1580.     how = (int)str_gnum(st[++sp]);
  1581.     return shutdown(fileno(stio->ifp), how) >= 0;
  1582.  
  1583. nuts:
  1584.     if (dowarn)
  1585.     warn("shutdown() on closed fd");
  1586.     errno = EBADF;
  1587.     return FALSE;
  1588.  
  1589. }
  1590.  
  1591. int
  1592. do_sopt(optype, stab, arglast)
  1593. int optype;
  1594. STAB *stab;
  1595. int *arglast;
  1596. {
  1597.     register STR **st = stack->ary_array;
  1598.     register int sp = arglast[1];
  1599.     register STIO *stio;
  1600.     int fd;
  1601.     int lvl;
  1602.     int optname;
  1603.  
  1604.     if (!stab)
  1605.     goto nuts;
  1606.  
  1607.     stio = stab_io(stab);
  1608.     if (!stio || !stio->ifp)
  1609.     goto nuts;
  1610.  
  1611.     fd = fileno(stio->ifp);
  1612.     lvl = (int)str_gnum(st[sp+1]);
  1613.     optname = (int)str_gnum(st[sp+2]);
  1614.     switch (optype) {
  1615.     case O_GSOCKOPT:
  1616.     st[sp] = str_2mortal(Str_new(22,257));
  1617.     st[sp]->str_cur = 256;
  1618.     st[sp]->str_pok = 1;
  1619.     if (getsockopt(fd, lvl, optname, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
  1620.         goto nuts;
  1621.     break;
  1622.     case O_SSOCKOPT:
  1623.     st[sp] = st[sp+3];
  1624.     if (setsockopt(fd, lvl, optname, st[sp]->str_ptr, st[sp]->str_cur) < 0)
  1625.         goto nuts;
  1626.     st[sp] = &str_yes;
  1627.     break;
  1628.     }
  1629.     
  1630.     return sp;
  1631.  
  1632. nuts:
  1633.     if (dowarn)
  1634.     warn("[gs]etsockopt() on closed fd");
  1635.     st[sp] = &str_undef;
  1636.     errno = EBADF;
  1637.     return sp;
  1638.  
  1639. }
  1640.  
  1641. int
  1642. do_getsockname(optype, stab, arglast)
  1643. int optype;
  1644. STAB *stab;
  1645. int *arglast;
  1646. {
  1647.     register STR **st = stack->ary_array;
  1648.     register int sp = arglast[1];
  1649.     register STIO *stio;
  1650.     int fd;
  1651.  
  1652.     if (!stab)
  1653.     goto nuts;
  1654.  
  1655.     stio = stab_io(stab);
  1656.     if (!stio || !stio->ifp)
  1657.     goto nuts;
  1658.  
  1659.     st[sp] = str_2mortal(Str_new(22,257));
  1660.     st[sp]->str_cur = 256;
  1661.     st[sp]->str_pok = 1;
  1662.     fd = fileno(stio->ifp);
  1663.     switch (optype) {
  1664.     case O_GETSOCKNAME:
  1665.     if (getsockname(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
  1666.         goto nuts2;
  1667.     break;
  1668.     case O_GETPEERNAME:
  1669.     if (getpeername(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
  1670.         goto nuts2;
  1671.     break;
  1672.     }
  1673.     
  1674.     return sp;
  1675.  
  1676. nuts:
  1677.     if (dowarn)
  1678.     warn("get{sock,peer}name() on closed fd");
  1679.     errno = EBADF;
  1680. nuts2:
  1681.     st[sp] = &str_undef;
  1682.     return sp;
  1683.  
  1684. }
  1685.  
  1686. int
  1687. do_ghent(which,gimme,arglast)
  1688. int which;
  1689. int gimme;
  1690. int *arglast;
  1691. {
  1692.     register ARRAY *ary = stack;
  1693.     register int sp = arglast[0];
  1694.     register char **elem;
  1695.     register STR *str;
  1696.     struct hostent *gethostbyname();
  1697.     struct hostent *gethostbyaddr();
  1698. #ifdef HAS_GETHOSTENT
  1699.     struct hostent *gethostent();
  1700. #endif
  1701.     struct hostent *hent;
  1702.     unsigned long len;
  1703.  
  1704.     if (gimme != G_ARRAY) {
  1705.     astore(ary, ++sp, str_mortal(&str_undef));
  1706.     return sp;
  1707.     }
  1708.  
  1709.     if (which == O_GHBYNAME) {
  1710.     char *name = str_get(ary->ary_array[sp+1]);
  1711.  
  1712.     hent = gethostbyname(name);
  1713.     }
  1714.     else if (which == O_GHBYADDR) {
  1715.     STR *addrstr = ary->ary_array[sp+1];
  1716.     int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
  1717.     char *addr = str_get(addrstr);
  1718.  
  1719.     hent = gethostbyaddr(addr,addrstr->str_cur,addrtype);
  1720.     }
  1721.     else
  1722. #ifdef HAS_GETHOSTENT
  1723.     hent = gethostent();
  1724. #else
  1725.     fatal("gethostent not implemented");
  1726. #endif
  1727.     if (hent) {
  1728. #ifndef lint
  1729.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1730.     str_set(str, hent->h_name);
  1731.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1732.     for (elem = hent->h_aliases; *elem; elem++) {
  1733.         str_cat(str, *elem);
  1734.         if (elem[1])
  1735.         str_ncat(str," ",1);
  1736.     }
  1737.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1738.     str_numset(str, (double)hent->h_addrtype);
  1739.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1740.     len = hent->h_length;
  1741.     str_numset(str, (double)len);
  1742. #ifdef h_addr
  1743.     for (elem = hent->h_addr_list; *elem; elem++) {
  1744.         (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1745.         str_nset(str, *elem, len);
  1746.     }
  1747. #else
  1748.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1749.     str_nset(str, hent->h_addr, len);
  1750. #endif /* h_addr */
  1751. #else /* lint */
  1752.     elem = Nullch;
  1753.     elem = elem;
  1754.     (void)astore(ary, ++sp, str_mortal(&str_no));
  1755. #endif /* lint */
  1756.     }
  1757.  
  1758.     return sp;
  1759. }
  1760.  
  1761. int
  1762. do_gnent(which,gimme,arglast)
  1763. int which;
  1764. int gimme;
  1765. int *arglast;
  1766. {
  1767.     register ARRAY *ary = stack;
  1768.     register int sp = arglast[0];
  1769.     register char **elem;
  1770.     register STR *str;
  1771.     struct netent *getnetbyname();
  1772.     struct netent *getnetbyaddr();
  1773.     struct netent *getnetent();
  1774.     struct netent *nent;
  1775.  
  1776.     if (gimme != G_ARRAY) {
  1777.     astore(ary, ++sp, str_mortal(&str_undef));
  1778.     return sp;
  1779.     }
  1780.  
  1781.     if (which == O_GNBYNAME) {
  1782.     char *name = str_get(ary->ary_array[sp+1]);
  1783.  
  1784.     nent = getnetbyname(name);
  1785.     }
  1786.     else if (which == O_GNBYADDR) {
  1787.     unsigned long addr = U_L(str_gnum(ary->ary_array[sp+1]));
  1788.     int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
  1789.  
  1790.     nent = getnetbyaddr((long)addr,addrtype);
  1791.     }
  1792.     else
  1793.     nent = getnetent();
  1794.  
  1795.     if (nent) {
  1796. #ifndef lint
  1797.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1798.     str_set(str, nent->n_name);
  1799.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1800.     for (elem = nent->n_aliases; *elem; elem++) {
  1801.         str_cat(str, *elem);
  1802.         if (elem[1])
  1803.         str_ncat(str," ",1);
  1804.     }
  1805.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1806.     str_numset(str, (double)nent->n_addrtype);
  1807.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1808.     str_numset(str, (double)nent->n_net);
  1809. #else /* lint */
  1810.     elem = Nullch;
  1811.     elem = elem;
  1812.     (void)astore(ary, ++sp, str_mortal(&str_no));
  1813. #endif /* lint */
  1814.     }
  1815.  
  1816.     return sp;
  1817. }
  1818.  
  1819. int
  1820. do_gpent(which,gimme,arglast)
  1821. int which;
  1822. int gimme;
  1823. int *arglast;
  1824. {
  1825.     register ARRAY *ary = stack;
  1826.     register int sp = arglast[0];
  1827.     register char **elem;
  1828.     register STR *str;
  1829.     struct protoent *getprotobyname();
  1830.     struct protoent *getprotobynumber();
  1831.     struct protoent *getprotoent();
  1832.     struct protoent *pent;
  1833.  
  1834.     if (gimme != G_ARRAY) {
  1835.     astore(ary, ++sp, str_mortal(&str_undef));
  1836.     return sp;
  1837.     }
  1838.  
  1839.     if (which == O_GPBYNAME) {
  1840.     char *name = str_get(ary->ary_array[sp+1]);
  1841.  
  1842.     pent = getprotobyname(name);
  1843.     }
  1844.     else if (which == O_GPBYNUMBER) {
  1845.     int proto = (int)str_gnum(ary->ary_array[sp+1]);
  1846.  
  1847.     pent = getprotobynumber(proto);
  1848.     }
  1849.     else
  1850.     pent = getprotoent();
  1851.  
  1852.     if (pent) {
  1853. #ifndef lint
  1854.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1855.     str_set(str, pent->p_name);
  1856.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1857.     for (elem = pent->p_aliases; *elem; elem++) {
  1858.         str_cat(str, *elem);
  1859.         if (elem[1])
  1860.         str_ncat(str," ",1);
  1861.     }
  1862.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1863.     str_numset(str, (double)pent->p_proto);
  1864. #else /* lint */
  1865.     elem = Nullch;
  1866.     elem = elem;
  1867.     (void)astore(ary, ++sp, str_mortal(&str_no));
  1868. #endif /* lint */
  1869.     }
  1870.  
  1871.     return sp;
  1872. }
  1873.  
  1874. int
  1875. do_gsent(which,gimme,arglast)
  1876. int which;
  1877. int gimme;
  1878. int *arglast;
  1879. {
  1880.     register ARRAY *ary = stack;
  1881.     register int sp = arglast[0];
  1882.     register char **elem;
  1883.     register STR *str;
  1884.     struct servent *getservbyname();
  1885.     struct servent *getservbynumber();
  1886.     struct servent *getservent();
  1887.     struct servent *sent;
  1888.  
  1889.     if (gimme != G_ARRAY) {
  1890.     astore(ary, ++sp, str_mortal(&str_undef));
  1891.     return sp;
  1892.     }
  1893.  
  1894.     if (which == O_GSBYNAME) {
  1895.     char *name = str_get(ary->ary_array[sp+1]);
  1896.     char *proto = str_get(ary->ary_array[sp+2]);
  1897.  
  1898.     if (proto && !*proto)
  1899.         proto = Nullch;
  1900.  
  1901.     sent = getservbyname(name,proto);
  1902.     }
  1903.     else if (which == O_GSBYPORT) {
  1904.     int port = (int)str_gnum(ary->ary_array[sp+1]);
  1905.     char *proto = str_get(ary->ary_array[sp+2]);
  1906.  
  1907.     sent = getservbyport(port,proto);
  1908.     }
  1909.     else
  1910.     sent = getservent();
  1911.     if (sent) {
  1912. #ifndef lint
  1913.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1914.     str_set(str, sent->s_name);
  1915.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1916.     for (elem = sent->s_aliases; *elem; elem++) {
  1917.         str_cat(str, *elem);
  1918.         if (elem[1])
  1919.         str_ncat(str," ",1);
  1920.     }
  1921.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1922. #ifdef HAS_NTOHS
  1923.     str_numset(str, (double)ntohs(sent->s_port));
  1924. #else
  1925.     str_numset(str, (double)(sent->s_port));
  1926. #endif
  1927.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1928.     str_set(str, sent->s_proto);
  1929. #else /* lint */
  1930.     elem = Nullch;
  1931.     elem = elem;
  1932.     (void)astore(ary, ++sp, str_mortal(&str_no));
  1933. #endif /* lint */
  1934.     }
  1935.  
  1936.     return sp;
  1937. }
  1938.  
  1939. #endif /* HAS_SOCKET */
  1940.  
  1941. #ifdef HAS_SELECT
  1942. int
  1943. do_select(gimme,arglast)
  1944. int gimme;
  1945. int *arglast;
  1946. {
  1947.     register STR **st = stack->ary_array;
  1948.     register int sp = arglast[0];
  1949.     register int i;
  1950.     register int j;
  1951.     register char *s;
  1952.     register STR *str;
  1953.     double value;
  1954.     int maxlen = 0;
  1955.     int nfound;
  1956.     struct timeval timebuf;
  1957.     struct timeval *tbuf = &timebuf;
  1958.     int growsize;
  1959. #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
  1960.     int masksize;
  1961.     int offset;
  1962.     char *fd_sets[4];
  1963.     int k;
  1964.  
  1965. #if BYTEORDER & 0xf0000
  1966. #define ORDERBYTE (0x88888888 - BYTEORDER)
  1967. #else
  1968. #define ORDERBYTE (0x4444 - BYTEORDER)
  1969. #endif
  1970.  
  1971. #endif
  1972.  
  1973.     for (i = 1; i <= 3; i++) {
  1974.     j = st[sp+i]->str_cur;
  1975.     if (maxlen < j)
  1976.         maxlen = j;
  1977.     }
  1978.  
  1979. #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
  1980.     growsize = maxlen;        /* little endians can use vecs directly */
  1981. #else
  1982. #ifdef NFDBITS
  1983.  
  1984. #ifndef NBBY
  1985. #define NBBY 8
  1986. #endif
  1987.  
  1988.     masksize = NFDBITS / NBBY;
  1989. #else
  1990.     masksize = sizeof(long);    /* documented int, everyone seems to use long */
  1991. #endif
  1992.     growsize = maxlen + (masksize - (maxlen % masksize));
  1993.     Zero(&fd_sets[0], 4, char*);
  1994. #endif
  1995.  
  1996.     for (i = 1; i <= 3; i++) {
  1997.     str = st[sp+i];
  1998.     j = str->str_len;
  1999.     if (j < growsize) {
  2000.         if (str->str_pok) {
  2001.         Str_Grow(str,growsize);
  2002.         s = str_get(str) + j;
  2003.         while (++j <= growsize) {
  2004.             *s++ = '\0';
  2005.         }
  2006.         }
  2007.         else if (str->str_ptr) {
  2008.         Safefree(str->str_ptr);
  2009.         str->str_ptr = Nullch;
  2010.         }
  2011.     }
  2012. #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
  2013.     s = str->str_ptr;
  2014.     if (s) {
  2015.         New(403, fd_sets[i], growsize, char);
  2016.         for (offset = 0; offset < growsize; offset += masksize) {
  2017.         for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
  2018.             fd_sets[i][j+offset] = s[(k % masksize) + offset];
  2019.         }
  2020.     }
  2021. #endif
  2022.     }
  2023.     str = st[sp+4];
  2024.     if (str->str_nok || str->str_pok) {
  2025.     value = str_gnum(str);
  2026.     if (value < 0.0)
  2027.         value = 0.0;
  2028.     timebuf.tv_sec = (long)value;
  2029.     value -= (double)timebuf.tv_sec;
  2030.     timebuf.tv_usec = (long)(value * 1000000.0);
  2031.     }
  2032.     else
  2033.     tbuf = Null(struct timeval*);
  2034.  
  2035. #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
  2036.     nfound = select(
  2037.     maxlen * 8,
  2038.     st[sp+1]->str_ptr,
  2039.     st[sp+2]->str_ptr,
  2040.     st[sp+3]->str_ptr,
  2041.     tbuf);
  2042. #else
  2043.     nfound = select(
  2044.     maxlen * 8,
  2045.     fd_sets[1],
  2046.     fd_sets[2],
  2047.     fd_sets[3],
  2048.     tbuf);
  2049.     for (i = 1; i <= 3; i++) {
  2050.     if (fd_sets[i]) {
  2051.         str = st[sp+i];
  2052.         s = str->str_ptr;
  2053.         for (offset = 0; offset < growsize; offset += masksize) {
  2054.         for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
  2055.             s[(k % masksize) + offset] = fd_sets[i][j+offset];
  2056.         }
  2057.     }
  2058.     }
  2059. #endif
  2060.  
  2061.     st[++sp] = str_mortal(&str_no);
  2062.     str_numset(st[sp], (double)nfound);
  2063.     if (gimme == G_ARRAY && tbuf) {
  2064.     value = (double)(timebuf.tv_sec) +
  2065.         (double)(timebuf.tv_usec) / 1000000.0;
  2066.     st[++sp] = str_mortal(&str_no);
  2067.     str_numset(st[sp], value);
  2068.     }
  2069.     return sp;
  2070. }
  2071. #endif /* SELECT */
  2072.  
  2073. #ifdef HAS_SOCKET
  2074. int
  2075. do_spair(stab1, stab2, arglast)
  2076. STAB *stab1;
  2077. STAB *stab2;
  2078. int *arglast;
  2079. {
  2080.     register STR **st = stack->ary_array;
  2081.     register int sp = arglast[2];
  2082.     register STIO *stio1;
  2083.     register STIO *stio2;
  2084.     int domain, type, protocol, fd[2];
  2085.  
  2086.     if (!stab1 || !stab2)
  2087.     return FALSE;
  2088.  
  2089.     stio1 = stab_io(stab1);
  2090.     stio2 = stab_io(stab2);
  2091.     if (!stio1)
  2092.     stio1 = stab_io(stab1) = stio_new();
  2093.     else if (stio1->ifp)
  2094.     do_close(stab1,FALSE);
  2095.     if (!stio2)
  2096.     stio2 = stab_io(stab2) = stio_new();
  2097.     else if (stio2->ifp)
  2098.     do_close(stab2,FALSE);
  2099.  
  2100.     domain = (int)str_gnum(st[++sp]);
  2101.     type = (int)str_gnum(st[++sp]);
  2102.     protocol = (int)str_gnum(st[++sp]);
  2103. #ifdef TAINT
  2104.     taintproper("Insecure dependency in socketpair");
  2105. #endif
  2106. #ifdef HAS_SOCKETPAIR
  2107.     if (socketpair(domain,type,protocol,fd) < 0)
  2108.     return FALSE;
  2109. #else
  2110.     fatal("Socketpair unimplemented");
  2111. #endif
  2112.     stio1->ifp = fdopen(fd[0], "r");
  2113.     stio1->ofp = fdopen(fd[0], "w");
  2114.     stio1->type = 's';
  2115.     stio2->ifp = fdopen(fd[1], "r");
  2116.     stio2->ofp = fdopen(fd[1], "w");
  2117.     stio2->type = 's';
  2118.     if (!stio1->ifp || !stio1->ofp || !stio2->ifp || !stio2->ofp) {
  2119.     if (stio1->ifp) fclose(stio1->ifp);
  2120.     if (stio1->ofp) fclose(stio1->ofp);
  2121.     if (!stio1->ifp && !stio1->ofp) close(fd[0]);
  2122.     if (stio2->ifp) fclose(stio2->ifp);
  2123.     if (stio2->ofp) fclose(stio2->ofp);
  2124.     if (!stio2->ifp && !stio2->ofp) close(fd[1]);
  2125.     return FALSE;
  2126.     }
  2127.  
  2128.     return TRUE;
  2129. }
  2130.  
  2131. #endif /* HAS_SOCKET */
  2132.  
  2133. int
  2134. do_gpwent(which,gimme,arglast)
  2135. int which;
  2136. int gimme;
  2137. int *arglast;
  2138. {
  2139. #ifdef I_PWD
  2140.     register ARRAY *ary = stack;
  2141.     register int sp = arglast[0];
  2142.     register STR *str;
  2143.     struct passwd *getpwnam();
  2144.     struct passwd *getpwuid();
  2145.     struct passwd *getpwent();
  2146.     struct passwd *pwent;
  2147.  
  2148.     if (gimme != G_ARRAY) {
  2149.     astore(ary, ++sp, str_mortal(&str_undef));
  2150.     return sp;
  2151.     }
  2152.  
  2153.     if (which == O_GPWNAM) {
  2154.     char *name = str_get(ary->ary_array[sp+1]);
  2155.  
  2156.     pwent = getpwnam(name);
  2157.     }
  2158.     else if (which == O_GPWUID) {
  2159.     int uid = (int)str_gnum(ary->ary_array[sp+1]);
  2160.  
  2161.     pwent = getpwuid(uid);
  2162.     }
  2163.     else
  2164.     pwent = getpwent();
  2165.  
  2166.     if (pwent) {
  2167.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2168.     str_set(str, pwent->pw_name);
  2169.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2170.     str_set(str, pwent->pw_passwd);
  2171.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2172.     str_numset(str, (double)pwent->pw_uid);
  2173.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2174.     str_numset(str, (double)pwent->pw_gid);
  2175.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2176. #ifdef PWCHANGE
  2177.     str_numset(str, (double)pwent->pw_change);
  2178. #else
  2179. #ifdef PWQUOTA
  2180.     str_numset(str, (double)pwent->pw_quota);
  2181. #else
  2182. #ifdef PWAGE
  2183.     str_set(str, pwent->pw_age);
  2184. #endif
  2185. #endif
  2186. #endif
  2187.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2188. #ifdef PWCLASS
  2189.     str_set(str,pwent->pw_class);
  2190. #else
  2191. #ifdef PWCOMMENT
  2192.     str_set(str, pwent->pw_comment);
  2193. #endif
  2194. #endif
  2195.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2196.     str_set(str, pwent->pw_gecos);
  2197.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2198.     str_set(str, pwent->pw_dir);
  2199.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2200.     str_set(str, pwent->pw_shell);
  2201. #ifdef PWEXPIRE
  2202.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2203.     str_numset(str, (double)pwent->pw_expire);
  2204. #endif
  2205.     }
  2206.  
  2207.     return sp;
  2208. #else
  2209.     fatal("password routines not implemented");
  2210. #endif
  2211. }
  2212.  
  2213. int
  2214. do_ggrent(which,gimme,arglast)
  2215. int which;
  2216. int gimme;
  2217. int *arglast;
  2218. {
  2219. #ifdef I_GRP
  2220.     register ARRAY *ary = stack;
  2221.     register int sp = arglast[0];
  2222.     register char **elem;
  2223.     register STR *str;
  2224.     struct group *getgrnam();
  2225.     struct group *getgrgid();
  2226.     struct group *getgrent();
  2227.     struct group *grent;
  2228.  
  2229.     if (gimme != G_ARRAY) {
  2230.     astore(ary, ++sp, str_mortal(&str_undef));
  2231.     return sp;
  2232.     }
  2233.  
  2234.     if (which == O_GGRNAM) {
  2235.     char *name = str_get(ary->ary_array[sp+1]);
  2236.  
  2237.     grent = getgrnam(name);
  2238.     }
  2239.     else if (which == O_GGRGID) {
  2240.     int gid = (int)str_gnum(ary->ary_array[sp+1]);
  2241.  
  2242.     grent = getgrgid(gid);
  2243.     }
  2244.     else
  2245.     grent = getgrent();
  2246.  
  2247.     if (grent) {
  2248.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2249.     str_set(str, grent->gr_name);
  2250.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2251.     str_set(str, grent->gr_passwd);
  2252.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2253.     str_numset(str, (double)grent->gr_gid);
  2254.     (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2255.     for (elem = grent->gr_mem; *elem; elem++) {
  2256.         str_cat(str, *elem);
  2257.         if (elem[1])
  2258.         str_ncat(str," ",1);
  2259.     }
  2260.     }
  2261.  
  2262.     return sp;
  2263. #else
  2264.     fatal("group routines not implemented");
  2265. #endif
  2266. }
  2267.  
  2268. int
  2269. do_dirop(optype,stab,gimme,arglast)
  2270. int optype;
  2271. STAB *stab;
  2272. int gimme;
  2273. int *arglast;
  2274. {
  2275. #if defined(DIRENT) && defined(HAS_READDIR)
  2276.     register ARRAY *ary = stack;
  2277.     register STR **st = ary->ary_array;
  2278.     register int sp = arglast[1];
  2279.     register STIO *stio;
  2280.     long along;
  2281. #ifndef telldir
  2282.     long telldir();
  2283. #endif
  2284. #ifndef apollo
  2285.     struct DIRENT *readdir();
  2286. #endif
  2287.     register struct DIRENT *dp;
  2288.  
  2289.     if (!stab)
  2290.     goto nope;
  2291.     if (!(stio = stab_io(stab)))
  2292.     stio = stab_io(stab) = stio_new();
  2293.     if (!stio->dirp && optype != O_OPEN_DIR)
  2294.     goto nope;
  2295.     st[sp] = &str_yes;
  2296.     switch (optype) {
  2297.     case O_OPEN_DIR:
  2298.     if (stio->dirp)
  2299.         closedir(stio->dirp);
  2300.     if (!(stio->dirp = opendir(str_get(st[sp+1]))))
  2301.         goto nope;
  2302.     break;
  2303.     case O_READDIR:
  2304.     if (gimme == G_ARRAY) {
  2305.         --sp;
  2306.         /*SUPPRESS 560*/
  2307.         while (dp = readdir(stio->dirp)) {
  2308. #ifdef DIRNAMLEN
  2309.         (void)astore(ary,++sp,
  2310.           str_2mortal(str_make(dp->d_name,dp->d_namlen)));
  2311. #else
  2312.         (void)astore(ary,++sp,
  2313.           str_2mortal(str_make(dp->d_name,0)));
  2314. #endif
  2315.         }
  2316.     }
  2317.     else {
  2318.         if (!(dp = readdir(stio->dirp)))
  2319.         goto nope;
  2320.         st[sp] = str_mortal(&str_undef);
  2321. #ifdef DIRNAMLEN
  2322.         str_nset(st[sp], dp->d_name, dp->d_namlen);
  2323. #else
  2324.         str_set(st[sp], dp->d_name);
  2325. #endif
  2326.     }
  2327.     break;
  2328. #if MACH
  2329.     case O_TELLDIR:
  2330.     case O_SEEKDIR:
  2331.         goto nope;
  2332. #else
  2333.     case O_TELLDIR:
  2334.     st[sp] = str_mortal(&str_undef);
  2335.     str_numset(st[sp], (double)telldir(stio->dirp));
  2336.     break;
  2337.     case O_SEEKDIR:
  2338.     st[sp] = str_mortal(&str_undef);
  2339.     along = (long)str_gnum(st[sp+1]);
  2340.     (void)seekdir(stio->dirp,along);
  2341.     break;
  2342. #endif
  2343.     case O_REWINDDIR:
  2344.     st[sp] = str_mortal(&str_undef);
  2345.     (void)rewinddir(stio->dirp);
  2346.     break;
  2347.     case O_CLOSEDIR:
  2348.     st[sp] = str_mortal(&str_undef);
  2349.     (void)closedir(stio->dirp);
  2350.     stio->dirp = 0;
  2351.     break;
  2352.     }
  2353.     return sp;
  2354.  
  2355. nope:
  2356.     st[sp] = &str_undef;
  2357.     if (!errno)
  2358.     errno = EBADF;
  2359.     return sp;
  2360.  
  2361. #else
  2362.     fatal("Unimplemented directory operation");
  2363. #endif
  2364. }
  2365.  
  2366. apply(type,arglast)
  2367. int type;
  2368. int *arglast;
  2369. {
  2370.     register STR **st = stack->ary_array;
  2371.     register int sp = arglast[1];
  2372.     register int items = arglast[2] - sp;
  2373.     register int val;
  2374.     register int val2;
  2375.     register int tot = 0;
  2376.     char *s;
  2377.  
  2378. #ifdef TAINT
  2379.     for (st += ++sp; items--; st++)
  2380.     tainted |= (*st)->str_tainted;
  2381.     st = stack->ary_array;
  2382.     sp = arglast[1];
  2383.     items = arglast[2] - sp;
  2384. #endif
  2385.     switch (type) {
  2386.     case O_CHMOD:
  2387. #ifdef TAINT
  2388.     taintproper("Insecure dependency in chmod");
  2389. #endif
  2390.     if (--items > 0) {
  2391.         tot = items;
  2392.         val = (int)str_gnum(st[++sp]);
  2393.         while (items--) {
  2394.         if (chmod(str_get(st[++sp]),val))
  2395.             tot--;
  2396.         }
  2397.     }
  2398.     break;
  2399. #ifdef HAS_CHOWN
  2400.     case O_CHOWN:
  2401. #ifdef TAINT
  2402.     taintproper("Insecure dependency in chown");
  2403. #endif
  2404.     if (items > 2) {
  2405.         items -= 2;
  2406.         tot = items;
  2407.         val = (int)str_gnum(st[++sp]);
  2408.         val2 = (int)str_gnum(st[++sp]);
  2409.         while (items--) {
  2410.         if (chown(str_get(st[++sp]),val,val2))
  2411.             tot--;
  2412.         }
  2413.     }
  2414.     break;
  2415. #endif
  2416. #ifdef HAS_KILL
  2417.     case O_KILL:
  2418. #ifdef TAINT
  2419.     taintproper("Insecure dependency in kill");
  2420. #endif
  2421.     if (--items > 0) {
  2422.         tot = items;
  2423.         s = str_get(st[++sp]);
  2424.         if (isUPPER(*s)) {
  2425.         if (*s == 'S' && s[1] == 'I' && s[2] == 'G')
  2426.             s += 3;
  2427.         if (!(val = whichsig(s)))
  2428.             fatal("Unrecognized signal name \"%s\"",s);
  2429.         }
  2430.         else
  2431.         val = (int)str_gnum(st[sp]);
  2432.         if (val < 0) {
  2433.         val = -val;
  2434.         while (items--) {
  2435.             int proc = (int)str_gnum(st[++sp]);
  2436. #ifdef HAS_KILLPG
  2437.             if (killpg(proc,val))    /* BSD */
  2438. #else
  2439.             if (kill(-proc,val))    /* SYSV */
  2440. #endif
  2441.             tot--;
  2442.         }
  2443.         }
  2444.         else {
  2445.         while (items--) {
  2446.             if (kill((int)(str_gnum(st[++sp])),val))
  2447.             tot--;
  2448.         }
  2449.         }
  2450.     }
  2451.     break;
  2452. #endif
  2453.     case O_UNLINK:
  2454. #ifdef TAINT
  2455.     taintproper("Insecure dependency in unlink");
  2456. #endif
  2457.     tot = items;
  2458.     while (items--) {
  2459.         s = str_get(st[++sp]);
  2460.         if (euid || unsafe) {
  2461.         if (UNLINK(s))
  2462.             tot--;
  2463.         }
  2464.         else {    /* don't let root wipe out directories without -U */
  2465. #ifdef HAS_LSTAT
  2466.         if (lstat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
  2467. #else
  2468.         if (stat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
  2469. #endif
  2470.             tot--;
  2471.         else {
  2472.             if (UNLINK(s))
  2473.             tot--;
  2474.         }
  2475.         }
  2476.     }
  2477.     break;
  2478.     case O_UTIME:
  2479. #ifdef TAINT
  2480.     taintproper("Insecure dependency in utime");
  2481. #endif
  2482.     if (items > 2) {
  2483. #ifdef I_UTIME
  2484.         struct utimbuf utbuf;
  2485. #else
  2486.         struct {
  2487.         long    actime;
  2488.         long    modtime;
  2489.         } utbuf;
  2490. #endif
  2491.  
  2492.         Zero(&utbuf, sizeof utbuf, char);
  2493.         utbuf.actime = (long)str_gnum(st[++sp]);    /* time accessed */
  2494.         utbuf.modtime = (long)str_gnum(st[++sp]);    /* time modified */
  2495.         items -= 2;
  2496. #ifndef lint
  2497.         tot = items;
  2498.         while (items--) {
  2499.         if (utime(str_get(st[++sp]),&utbuf))
  2500.             tot--;
  2501.         }
  2502. #endif
  2503.     }
  2504.     else
  2505.         items = 0;
  2506.     break;
  2507.     }
  2508.     return tot;
  2509. }
  2510.  
  2511. /* Do the permissions allow some operation?  Assumes statcache already set. */
  2512.  
  2513. int
  2514. cando(bit, effective, statbufp)
  2515. int bit;
  2516. int effective;
  2517. register struct stat *statbufp;
  2518. {
  2519. #ifdef MSDOS
  2520.     /* [Comments and code from Len Reed]
  2521.      * MS-DOS "user" is similar to UNIX's "superuser," but can't write
  2522.      * to write-protected files.  The execute permission bit is set
  2523.      * by the Miscrosoft C library stat() function for the following:
  2524.      *        .exe files
  2525.      *        .com files
  2526.      *        .bat files
  2527.      *        directories
  2528.      * All files and directories are readable.
  2529.      * Directories and special files, e.g. "CON", cannot be
  2530.      * write-protected.
  2531.      * [Comment by Tom Dinger -- a directory can have the write-protect
  2532.      *        bit set in the file system, but DOS permits changes to
  2533.      *        the directory anyway.  In addition, all bets are off
  2534.      *        here for networked software, such as Novell and
  2535.      *        Sun's PC-NFS.]
  2536.      */
  2537.  
  2538.      return (bit & statbufp->st_mode) ? TRUE : FALSE;
  2539.  
  2540. #else /* ! MSDOS */
  2541.     if ((effective ? euid : uid) == 0) {    /* root is special */
  2542.     if (bit == S_IXUSR) {
  2543.         if (statbufp->st_mode & 0111 || S_ISDIR(statbufp->st_mode))
  2544.         return TRUE;
  2545.     }
  2546.     else
  2547.         return TRUE;        /* root reads and writes anything */
  2548.     return FALSE;
  2549.     }
  2550.     if (statbufp->st_uid == (effective ? euid : uid) ) {
  2551.     if (statbufp->st_mode & bit)
  2552.         return TRUE;    /* ok as "user" */
  2553.     }
  2554.     else if (ingroup((int)statbufp->st_gid,effective)) {
  2555.     if (statbufp->st_mode & bit >> 3)
  2556.         return TRUE;    /* ok as "group" */
  2557.     }
  2558.     else if (statbufp->st_mode & bit >> 6)
  2559.     return TRUE;    /* ok as "other" */
  2560.     return FALSE;
  2561. #endif /* ! MSDOS */
  2562. }
  2563.  
  2564. int
  2565. ingroup(testgid,effective)
  2566. int testgid;
  2567. int effective;
  2568. {
  2569.     if (testgid == (effective ? egid : gid))
  2570.     return TRUE;
  2571. #ifdef HAS_GETGROUPS
  2572. #ifndef NGROUPS
  2573. #define NGROUPS 32
  2574. #endif
  2575.     {
  2576.     GROUPSTYPE gary[NGROUPS];
  2577.     int anum;
  2578.  
  2579.     anum = getgroups(NGROUPS,gary);
  2580.     while (--anum >= 0)
  2581.         if (gary[anum] == testgid)
  2582.         return TRUE;
  2583.     }
  2584. #endif
  2585.     return FALSE;
  2586. }
  2587.  
  2588. #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
  2589.  
  2590. int
  2591. do_ipcget(optype, arglast)
  2592. int optype;
  2593. int *arglast;
  2594. {
  2595.     register STR **st = stack->ary_array;
  2596.     register int sp = arglast[0];
  2597.     key_t key;
  2598.     int n, flags;
  2599.  
  2600.     key = (key_t)str_gnum(st[++sp]);
  2601.     n = (optype == O_MSGGET) ? 0 : (int)str_gnum(st[++sp]);
  2602.     flags = (int)str_gnum(st[++sp]);
  2603.     errno = 0;
  2604.     switch (optype)
  2605.     {
  2606. #ifdef HAS_MSG
  2607.     case O_MSGGET:
  2608.     return msgget(key, flags);
  2609. #endif
  2610. #ifdef HAS_SEM
  2611.     case O_SEMGET:
  2612.     return semget(key, n, flags);
  2613. #endif
  2614. #ifdef HAS_SHM
  2615.     case O_SHMGET:
  2616.     return shmget(key, n, flags);
  2617. #endif
  2618. #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
  2619.     default:
  2620.     fatal("%s not implemented", opname[optype]);
  2621. #endif
  2622.     }
  2623.     return -1;            /* should never happen */
  2624. }
  2625.  
  2626. int
  2627. do_ipcctl(optype, arglast)
  2628. int optype;
  2629. int *arglast;
  2630. {
  2631.     register STR **st = stack->ary_array;
  2632.     register int sp = arglast[0];
  2633.     STR *astr;
  2634.     char *a;
  2635.     int id, n, cmd, infosize, getinfo, ret;
  2636.  
  2637.     id = (int)str_gnum(st[++sp]);
  2638.     n = (optype == O_SEMCTL) ? (int)str_gnum(st[++sp]) : 0;
  2639.     cmd = (int)str_gnum(st[++sp]);
  2640.     astr = st[++sp];
  2641.  
  2642.     infosize = 0;
  2643.     getinfo = (cmd == IPC_STAT);
  2644.  
  2645.     switch (optype)
  2646.     {
  2647. #ifdef HAS_MSG
  2648.     case O_MSGCTL:
  2649.     if (cmd == IPC_STAT || cmd == IPC_SET)
  2650.         infosize = sizeof(struct msqid_ds);
  2651.     break;
  2652. #endif
  2653. #ifdef HAS_SHM
  2654.     case O_SHMCTL:
  2655.     if (cmd == IPC_STAT || cmd == IPC_SET)
  2656.         infosize = sizeof(struct shmid_ds);
  2657.     break;
  2658. #endif
  2659. #ifdef HAS_SEM
  2660.     case O_SEMCTL:
  2661.     if (cmd == IPC_STAT || cmd == IPC_SET)
  2662.         infosize = sizeof(struct semid_ds);
  2663.     else if (cmd == GETALL || cmd == SETALL)
  2664.     {
  2665.         struct semid_ds semds;
  2666.         if (semctl(id, 0, IPC_STAT, &semds) == -1)
  2667.         return -1;
  2668.         getinfo = (cmd == GETALL);
  2669.         infosize = semds.sem_nsems * sizeof(short);
  2670.         /* "short" is technically wrong but much more portable
  2671.            than guessing about u_?short(_t)? */
  2672.     }
  2673.     break;
  2674. #endif
  2675. #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
  2676.     default:
  2677.     fatal("%s not implemented", opname[optype]);
  2678. #endif
  2679.     }
  2680.  
  2681.     if (infosize)
  2682.     {
  2683.     if (getinfo)
  2684.     {
  2685.         STR_GROW(astr, infosize+1);
  2686.         a = str_get(astr);
  2687.     }
  2688.     else
  2689.     {
  2690.         a = str_get(astr);
  2691.         if (astr->str_cur != infosize)
  2692.         {
  2693.         errno = EINVAL;
  2694.         return -1;
  2695.         }
  2696.     }
  2697.     }
  2698.     else
  2699.     {
  2700.     int i = (int)str_gnum(astr);
  2701.     a = (char *)i;        /* ouch */
  2702.     }
  2703.     errno = 0;
  2704.     switch (optype)
  2705.     {
  2706. #ifdef HAS_MSG
  2707.     case O_MSGCTL:
  2708.     ret = msgctl(id, cmd, a);
  2709.     break;
  2710. #endif
  2711. #ifdef HAS_SEM
  2712.     case O_SEMCTL:
  2713.     ret = semctl(id, n, cmd, a);
  2714.     break;
  2715. #endif
  2716. #ifdef HAS_SHM
  2717.     case O_SHMCTL:
  2718.     ret = shmctl(id, cmd, a);
  2719.     break;
  2720. #endif
  2721.     }
  2722.     if (getinfo && ret >= 0) {
  2723.     astr->str_cur = infosize;
  2724.     astr->str_ptr[infosize] = '\0';
  2725.     }
  2726.     return ret;
  2727. }
  2728.  
  2729. int
  2730. do_msgsnd(arglast)
  2731. int *arglast;
  2732. {
  2733. #ifdef HAS_MSG
  2734.     register STR **st = stack->ary_array;
  2735.     register int sp = arglast[0];
  2736.     STR *mstr;
  2737.     char *mbuf;
  2738.     int id, msize, flags;
  2739.  
  2740.     id = (int)str_gnum(st[++sp]);
  2741.     mstr = st[++sp];
  2742.     flags = (int)str_gnum(st[++sp]);
  2743.     mbuf = str_get(mstr);
  2744.     if ((msize = mstr->str_cur - sizeof(long)) < 0) {
  2745.     errno = EINVAL;
  2746.     return -1;
  2747.     }
  2748.     errno = 0;
  2749.     return msgsnd(id, mbuf, msize, flags);
  2750. #else
  2751.     fatal("msgsnd not implemented");
  2752. #endif
  2753. }
  2754.  
  2755. int
  2756. do_msgrcv(arglast)
  2757. int *arglast;
  2758. {
  2759. #ifdef HAS_MSG
  2760.     register STR **st = stack->ary_array;
  2761.     register int sp = arglast[0];
  2762.     STR *mstr;
  2763.     char *mbuf;
  2764.     long mtype;
  2765.     int id, msize, flags, ret;
  2766.  
  2767.     id = (int)str_gnum(st[++sp]);
  2768.     mstr = st[++sp];
  2769.     msize = (int)str_gnum(st[++sp]);
  2770.     mtype = (long)str_gnum(st[++sp]);
  2771.     flags = (int)str_gnum(st[++sp]);
  2772.     mbuf = str_get(mstr);
  2773.     if (mstr->str_cur < sizeof(long)+msize+1) {
  2774.     STR_GROW(mstr, sizeof(long)+msize+1);
  2775.     mbuf = str_get(mstr);
  2776.     }
  2777.     errno = 0;
  2778.     ret = msgrcv(id, mbuf, msize, mtype, flags);
  2779.     if (ret >= 0) {
  2780.     mstr->str_cur = sizeof(long)+ret;
  2781.     mstr->str_ptr[sizeof(long)+ret] = '\0';
  2782.     }
  2783.     return ret;
  2784. #else
  2785.     fatal("msgrcv not implemented");
  2786. #endif
  2787. }
  2788.  
  2789. int
  2790. do_semop(arglast)
  2791. int *arglast;
  2792. {
  2793. #ifdef HAS_SEM
  2794.     register STR **st = stack->ary_array;
  2795.     register int sp = arglast[0];
  2796.     STR *opstr;
  2797.     char *opbuf;
  2798.     int id, opsize;
  2799.  
  2800.     id = (int)str_gnum(st[++sp]);
  2801.     opstr = st[++sp];
  2802.     opbuf = str_get(opstr);
  2803.     opsize = opstr->str_cur;
  2804.     if (opsize < sizeof(struct sembuf)
  2805.     || (opsize % sizeof(struct sembuf)) != 0) {
  2806.     errno = EINVAL;
  2807.     return -1;
  2808.     }
  2809.     errno = 0;
  2810.     return semop(id, (struct sembuf *)opbuf, opsize/sizeof(struct sembuf));
  2811. #else
  2812.     fatal("semop not implemented");
  2813. #endif
  2814. }
  2815.  
  2816. int
  2817. do_shmio(optype, arglast)
  2818. int optype;
  2819. int *arglast;
  2820. {
  2821. #ifdef HAS_SHM
  2822.     register STR **st = stack->ary_array;
  2823.     register int sp = arglast[0];
  2824.     STR *mstr;
  2825.     char *mbuf, *shm;
  2826.     int id, mpos, msize;
  2827.     struct shmid_ds shmds;
  2828. #ifndef VOIDSHMAT
  2829.     extern char *shmat();
  2830. #endif
  2831.  
  2832.     id = (int)str_gnum(st[++sp]);
  2833.     mstr = st[++sp];
  2834.     mpos = (int)str_gnum(st[++sp]);
  2835.     msize = (int)str_gnum(st[++sp]);
  2836.     errno = 0;
  2837.     if (shmctl(id, IPC_STAT, &shmds) == -1)
  2838.     return -1;
  2839.     if (mpos < 0 || msize < 0 || mpos + msize > shmds.shm_segsz) {
  2840.     errno = EFAULT;        /* can't do as caller requested */
  2841.     return -1;
  2842.     }
  2843.     shm = (char*)shmat(id, (char*)NULL, (optype == O_SHMREAD) ? SHM_RDONLY : 0);
  2844.     if (shm == (char *)-1)    /* I hate System V IPC, I really do */
  2845.     return -1;
  2846.     mbuf = str_get(mstr);
  2847.     if (optype == O_SHMREAD) {
  2848.     if (mstr->str_cur < msize) {
  2849.         STR_GROW(mstr, msize+1);
  2850.         mbuf = str_get(mstr);
  2851.     }
  2852.     bcopy(shm + mpos, mbuf, msize);
  2853.     mstr->str_cur = msize;
  2854.     mstr->str_ptr[msize] = '\0';
  2855.     }
  2856.     else {
  2857.     int n;
  2858.  
  2859.     if ((n = mstr->str_cur) > msize)
  2860.         n = msize;
  2861.     bcopy(mbuf, shm + mpos, n);
  2862.     if (n < msize)
  2863.         bzero(shm + mpos + n, msize - n);
  2864.     }
  2865.     return shmdt(shm);
  2866. #else
  2867.     fatal("shm I/O not implemented");
  2868. #endif
  2869. }
  2870.  
  2871. #endif /* SYSV IPC */
  2872. @
  2873.  
  2874.  
  2875. 1.2
  2876. log
  2877. @Sprite version of stat() returns a few extra fields
  2878. @
  2879. text
  2880. @d1 1
  2881. a1 1
  2882. /* $RCSfile: doio.c,v $$Revision: 4.0.1.3 $$Date: 91/06/10 01:21:19 $
  2883. d9 12
  2884. d108 1
  2885. a108 1
  2886.     while (len && isspace(name[len-1]))
  2887. d150 2
  2888. a151 1
  2889.     for (name++; isspace(*name); name++) ;
  2890. d174 1
  2891. a174 1
  2892.         while (isspace(*name))
  2893. d176 1
  2894. a176 1
  2895.         if (isdigit(*name))
  2896. d199 1
  2897. a199 1
  2898.         while (isspace(*name))
  2899. d214 1
  2900. a214 1
  2901.         while (isspace(*name))
  2902. d231 1
  2903. a231 1
  2904.         while (len && isspace(name[len-1]))
  2905. d233 2
  2906. a234 1
  2907.         for (; isspace(*name); name++) ;
  2908. d240 2
  2909. a241 1
  2910.         for (; isspace(*name); name++) ;
  2911. d261 2
  2912. d264 9
  2913. a272 2
  2914.     else if (!(statbuf.st_mode & S_IFMT))
  2915.         stio->type = 's';    /* some OS's return 0 on fstat()ed socket */
  2916. d281 2
  2917. a282 1
  2918.         Safefree(saveofp);
  2919. d322 1
  2920. d325 1
  2921. d358 1
  2922. d361 1
  2923. d535 2
  2924. a536 1
  2925.     if (!stab)
  2926. d538 1
  2927. d635 1
  2928. d662 1
  2929. d677 2
  2930. a678 1
  2931.     if (!stab || !argstr)
  2932. d680 1
  2933. a680 3
  2934.     stio = stab_io(stab);
  2935.     if (!stio)
  2936.     return -1;
  2937. d893 1
  2938. a893 1
  2939. int
  2940. d910 1
  2941. a910 1
  2942.     if (!stab_io(tmpstab) ||
  2943. d919 1
  2944. a919 1
  2945.     if (!stab_io(tmpstab) ||
  2946. d959 1
  2947. a959 1
  2948.     while (isspace(*s))
  2949. d965 1
  2950. a965 1
  2951.     while (isdigit(*s))
  2952. d973 1
  2953. a973 1
  2954.     while (isdigit(*s))
  2955. d981 1
  2956. a981 1
  2957.     while (isdigit(*s))
  2958. d984 1
  2959. a984 1
  2960.     while (isspace(*s))
  2961. d1001 1
  2962. d1042 1
  2963. a1075 1
  2964.     laststype = O_STAT;
  2965. d1081 1
  2966. d1098 1
  2967. d1156 2
  2968. d1168 1
  2969. a1168 1
  2970.         fatal("-T and -B not implemented on filehandles\n");
  2971. d1175 1
  2972. d1189 5
  2973. a1193 2
  2974.     if (len <= 0)        /* null file is anything */
  2975.         return &str_yes;
  2976. d1308 2
  2977. a1309 1
  2978.     for (s = cmd; *s && isalpha(*s); s++) ;    /* catch VAR=val gizmo */
  2979. d1313 1
  2980. a1313 1
  2981.     if (*s != ' ' && !isalpha(*s) && index("$&*(){}[]'\";\\|?<>~`\n",*s)) {
  2982. d1327 1
  2983. a1327 1
  2984.     while (*s && isspace(*s)) s++;
  2985. d1330 1
  2986. a1330 1
  2987.     while (*s && !isspace(*s)) s++;
  2988. d1357 2
  2989. a1358 1
  2990.     if (!stab)
  2991. d1360 1
  2992. d1416 1
  2993. d1447 1
  2994. d1475 1
  2995. d1524 1
  2996. d1553 1
  2997. d1583 1
  2998. a1583 1
  2999.     st[sp] = str_2mortal(str_new(257));
  3000. d1603 1
  3001. d1626 1
  3002. a1626 1
  3003.     st[sp] = str_2mortal(str_new(257));
  3004. d1646 1
  3005. d2273 1
  3006. d2324 2
  3007. d2391 1
  3008. a2391 1
  3009.         if (isupper(*s)) {
  3010. @
  3011.  
  3012.  
  3013. 1.1
  3014. log
  3015. @Initial revision
  3016. @
  3017. text
  3018. @d791 11
  3019. @
  3020.